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

4

是否可以将函数的参数展开到一个通用类型的数组中?

我正在尝试为一个接受函数并返回函数的通用函数添加 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参数,不是吗? - Titian Cernicova-Dragomir
1个回答

5
您的解决方案基本正确,您只需要告诉TS Args 只能是类似数组的东西(在这种情况下是一组参数元组)。
export type Foo<State> = <Args extends any[]>(
    baz: (state: State, ...args: Args) => Partial<State>
) => (...args: Args) => any;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接