【发布时间】:2020-03-01 14:00:40
【问题描述】:
function validate<K>(validationFunc: (...args: (K extends Array<infer T> ? T : K)[]) => boolean, validationArgs: K[]): boolean {
let res: boolean;
for (const validationArg of validationArgs) {
if (Array.isArray(validationArg)) {
res = validationFunc(...validationArg);
} else {
// res = validationFunc(validationArg);
res = (validationFunc as (args: K) => boolean)(validationArg);
}
if(!res)
return false;
}
return true
}
注释行在参数处引发错误:the Argument of type 'K' is not assignable to parameter of type 'K extends (infer T)[] ? T : K'.ts(2345),而强制转换的版本可以正常工作,并且不会引发任何错误。
如this playground 所示。
为什么打字稿不能推断,在这一行,K 不能是 Array<any> 类型,因此允许传递给验证函数?
语义上:
如果第二个参数的类型为K[],则函数需要接受K 作为单个参数。
如果第二个参数是K[][]类型,函数需要接受K的多个参数。
例如
validate((x: number) => x%2, [1, 2, 3])应该没问题
validate((a: string, b: string) => a === b, [['a', 'a'], ['b', 'b']])应该没问题
validate((x: number) => x%2, ['a', 'b']) 应该会抛出错误
validate((x: number) => x%2, [['a', 'a'], ['b', 'b']]) 应该会抛出错误
编辑:
validate((x: number) => x % 2 === 0, [[1, 2, 3]]) 也应该抛出错误,因为 validate 会破坏 number[][] 一次,并尝试使用 number[] 调用 (x: number) => boolean
【问题讨论】:
-
我 tested it on TS playground 我得到了你所期望的。您使用 TS 的哪个版本/编译器选项?
-
我用的是最新版
3.6.4。这些例子只是为了说明,我想在语义上实现什么。问题不在于方法声明(在我的代码和操场上运行良好)。问题出在身体上。我认为我不应该被要求投射validationFunc。该问题在操场上变得可见(第 10 行)(请参阅有问题的编辑)
标签: typescript type-inference typescript-generics