是否可以在 TypeScript 中传播独特的泛型类型?

Posted

技术标签:

【中文标题】是否可以在 TypeScript 中传播独特的泛型类型?【英文标题】:Is it possible to spread unique generic types in TypeScript? 【发布时间】:2019-11-04 00:19:43 【问题描述】:

是否可以将函数的参数分散到泛型数组中?

我正在尝试将 TypeScript 类型添加到接受一个函数并返回一个函数的泛型函数中。传递函数的参数与返回函数的参数相关。我希望消费者能够向传入的函数添加类型,并让这些类型出现在返回的函数中。

我有一个基本的解决方案,但它只适用于固定数量的参数。是否可以通过以下方式传播泛型参数?

使用示例:

type Foo = // Generic solution here

const bar = foo((state, name: string, age: number));

bar('John', 22); // All good
bar('John', 'Doe'); // Type Error, 'Doe' is not a number

const baz = foo((state, firstName: string, lastName: string, age: number));

baz('John', 'Doe', 22)

这是用于 React Hook 集成的。有一些非常好的例子,提供者在使 TypeScript 类型安全对他们的消费者来说真的很容易方面做得很好。 一个很好的例子是来自 React Redux 的 TypedUseSelectorHook。 https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-redux/index.d.ts#L556

尝试 1 扩散的解决方案。但不幸的是,所有类型都是所有可能类型的联合。

export type foo<State> = <Args>(
    baz: (state: State, ...args: Args[]) => Partial<State>
) => (...args: Args[]) => any;

尝试 2 具有“固定”数量参数的解决方案。这可行,但自动完成会显示所有参数。如果消费者尝试使用的类型数量超过添加的类型,TypeScript 会很不高兴。

type foo<State> = <
    Arg0 = void,
    Arg1 = void,
    Arg2 = void,
    Arg3 = void,
    Arg4 = void,
    Arg5 = void
>(
    baz: (
        state: State,
        arg0: Arg0,
        arg1: Arg1,
        arg2: Arg2,
        arg3: Arg3,
        arg4: Arg4,
        arg5: Arg5
    ) => Partial<State>
) => (
    arg0: Arg0,
    arg1: Arg1,
    arg2: Arg2,
    arg3: Arg3,
    arg4: Arg4,
    arg5: Arg5
) => any;

我想从事的工作是这样的:

type Foo<State> = <PassedArgs>(
    baz: (
        state: State,
        ...args: PassedArgs // Error: A rest parameter must be of an array type.
    ) => Partial<State>
) => (args: PassedArgs) => any;

这将允许消费者传入一个接受任意数量参数和参数类型的函数,并且返回函数将被正确键入。

【问题讨论】:

不应该barbaz 也采取state 吗?根据你的尝试? 【参考方案1】:

您的解决方案几乎是正确的,您只需要告诉 TS Args 被限制为类似数组的东西(在这种情况下为参数元组)。

export type Foo<State> = <Args extends any[]>(
    baz: (state: State, ...args: Args) => Partial<State>
) => (...args: Args) => any;

【讨论】:

以上是关于是否可以在 TypeScript 中传播独特的泛型类型?的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript中的泛型

TypeScript 中每个键的泛型映射对象类型

扩展类型的泛型和 Typescript 中的普通类型有啥区别?

选择Typescript的原因:支持定义执行时的泛型参数

将泛型值推送到 Typescript 中泛型类中的泛型列表

如何在带有 React 的 Typescript/JSX 中使用带有箭头函数的泛型?