是否可以在TypeScript中传播唯一的泛型类型?

时间:2019-06-21 07:07:41

标签: typescript

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

我正在尝试将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的TypedUseSelectorHookhttps://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;

**Attempt 2**
A solution with a 'fixed' number of parameters. This works, but the autocomplete shows all parameters. And if the consumer tries to use more than the number of types added TypeScript will be unhappy.

```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;

这将允许使用者传递一个带有任意数量的参数和参数类型的函数,并且返回函数将被正确键入。

1 个答案:

答案 0 :(得分:0)

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

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