[英]Assigning arrow function to generic function type with TypeScript
我已经对类似的问题做了一些探讨,但是找不到有效的解决方案。 我有一些通用函数,但是我似乎无法正确实现它们。
简而言之,我有这个:
/** Takes three values of the same type and collapses them into one */
declare type MergeFunction = <T>(def: T, file?: T, arg?: T) => T
/** The implementation I'm having trouble with. Merge three arrays of the same type. */
const arrayMerge: MergeFunction = <T>(def: T[], file: T[] = [], arg: T[] = []): T[] => [ ].concat(def).concat(file || [ ]).concat(arg || [ ])
但是,出现编译器错误:
Property 'arrayMerge' is incompatible with index signature.
Type '<A>(def: A[], file?: A[], arg?: A[]) => A[]' is not assignable to type 'MergeFunction'.
Types of parameters 'def' and 'def' are incompatible.
Type 'T' is not assignable to type '{}[]'.
我实际上如何实现这种类型?
如定义的那样,类型MergeFunction
的函数必须对调用者指定的任何类型T
起作用。 所以arrayMerge
不是 MergeFunction
,因为它只接受数组。 这是按指定方式实现MergeFunction
的一种方法:
declare type MergeFunction = <T>(def: T, file?: T, arg?: T) => T;
const returnLastSpecifiedThing: MergeFunction = <T>(def: T, file?: T, arg?: T) =>
typeof arg !== 'undefined' ? arg :
typeof file !== 'undefined' ? file :
def;
实际上,实现诸如MergeFunction
类的类型时,您唯一可以做的安全的事情就是返回其中一个输入,因为您对T
一无所知,因为调用者对此负责。 当然没有办法确保T
是一个数组。
也许您是说MergeFunction
是实现者选择通用参数T
。 在这种情况下,可以使类型成为泛型而不是函数 :
declare type MergeFunction<T> = (def: T, file?: T, arg?: T) => T;
注意<T>
如何从函数移到类型。 原始定义是指泛型函数类型的特定类型别名 ,而新定义是泛型类型别名 ,当您插入T
的值时, 泛型类型别名指的是特定函数类型 。 (抱歉,这很令人困惑。)现在,实现这种特定类型的方法要容易得多。 例如:
const concatenateStrings: MergeFunction<string> =
(def: string, file?: string, arg?: string) =>
def + (file ? file : "") + (arg ? arg: "");
函数concatenateStrings
是MergeFunction<string>
。
此时,将arrayMerge
表示为某种MergeFunction<>
似乎应该很简单。 不幸的是,事实并非如此。 TypeScript缺少您在此处需要的通用类型 。 你想要说的是一样的东西:
const arrayMerge: <T> MergeFunction<T[]> = // invalid syntax
(def: T[], file: T[] = [], arg: T[] = []): T[] =>
([] as T[]).concat(def).concat(file || []).concat(arg || []);
但是您不能直接执行此操作(如链接问题所述)。 您可以获得的最接近的结果是添加一个间接层,例如函数调用:
const makeArrayMerge = <T>(): MergeFunction<T[]> =>
(def: T[], file: T[] = [], arg: T[] = []): T[] =>
([] as T[]).concat(def).concat(file || []).concat(arg || []);
现在, makeArrayMerge
是一个函数,当使用指定的类型参数T
调用该函数时,将生成 MergeFunction<T>
。 这可行,但是更难使用(并且不会以您想要的方式推断类型):
const numArray = makeArrayMerge<number>()([0, 1, 2], [3, 4, 5]);
哦,鉴于TypeScript泛型的局限性,这是我能做的最好的事情。 由您决定是否确实需要上述间接寻址或某些特定的数组类型是否适合您。 希望能有所帮助。 祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.