[英]use typescript generics to infer type of param function
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 commented line throws an Error at the argument: the Argument of type 'K' is not assignable to parameter of type 'K extends (infer T)[]? T: K'.ts(2345)
注释行在参数处引发错误:
the Argument of type 'K' is not assignable to parameter of type 'K extends (infer T)[]? T: K'.ts(2345)
the Argument of type 'K' is not assignable to parameter of type 'K extends (infer T)[]? T: K'.ts(2345)
, whereas the casted version works, and does not throw any errors. the Argument of type 'K' is not assignable to parameter of type 'K extends (infer T)[]? T: K'.ts(2345)
,而铸造版本可以工作,并且不会抛出任何错误。 As seen in this playground .正如在这个操场上看到的那样。
Why is typescript not able to infer, that on this line, K
cannot be of type Array<any>
and thus is allowed to be passed to the validation function?为什么 typescript 无法推断,在这一行上,
K
不能是Array<any>
类型,因此允许传递给验证 function?
Semantically: If the second argument is of type K[]
, the function needs to accept K
as a single parameter.语义上:如果第二个参数的类型是
K[]
,则 function 需要接受K
作为单个参数。 If the second argument is of type K[][]
, the function needs to accept multiple arguments of K
.如果第二个参数的类型是
K[][]
,则 function 需要接受多个 arguments 的K
。
Eg例如
validate((x: number) => x%2, [1, 2, 3])
should be ok validate((x: number) => x%2, [1, 2, 3])
应该没问题
validate((a: string, b: string) => a === b, [['a', 'a'], ['b', 'b']])
should be ok validate((a: string, b: string) => a === b, [['a', 'a'], ['b', 'b']])
应该没问题
validate((x: number) => x%2, ['a', 'b'])
should throw an error validate((x: number) => x%2, ['a', 'b'])
应该抛出一个错误
validate((x: number) => x%2, [['a', 'a'], ['b', 'b']])
should throw an error validate((x: number) => x%2, [['a', 'a'], ['b', 'b']])
应该抛出一个错误
EDIT: validate((x: number) => x % 2 === 0, [[1, 2, 3]])
should also throw an error, since validate would destructure the number[][]
once, and try to call (x: number) => boolean
with number[]
编辑:
validate((x: number) => x % 2 === 0, [[1, 2, 3]])
也应该抛出一个错误,因为 validate 会破坏number[][]
一次,并尝试呼叫(x: number) => boolean
与number[]
I don't think you need to infer the type of the param function.我认为您不需要推断参数 function 的类型。 Your validation arguments can be just
K[] | K[][]
您的验证 arguments 可以只是
K[] | K[][]
K[] | K[][]
as you explained it. K[] | K[][]
正如你所解释的那样。
I also did a small change when you call the validate function x % 2
should be wrapped in Boolean()
otherwise the return value would be incorrect.当您调用 validate function
x % 2
时,我还做了一个小改动,应将其包裹在Boolean()
中,否则返回值将不正确。
function validate<T extends (...args: any) => boolean, P extends Parameters<T>>(validationFunc: T, validationArgs: P[]): boolean {
let res: boolean;
for (const validationArg of validationArgs) {
res = validationFunc(validationArg);
if(!res)
return false;
}
return true
}
function simplified<T extends (...args: any) => boolean, P extends Parameters<T>>(validationFunc: T, validationArgs: P[]): boolean {
return validationArgs.every((args) => validationFunc(args));
}
validate((x: number) => Boolean(x % 2), [[1], [2], [3]]) // should be ok
validate((a: string, b: string) => a === b, [['a', 'a'], ['b', 'b']]) // should be ok
validate((x: number) => Boolean(x % 2), [['a'], ['b']]) // should throw an error
validate((x: number) => Boolean(x % 2), [['a', 'a'], ['b', 'b']]) // should throw an error
validate((x: number) => x % 2 === 0, [[1, 2, 3]]); // should throw an error
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.