TypeScript:有没有一种方法可以检查函数的通用性?

时间:2018-07-02 20:52:45

标签: typescript

给出以下代码:

type Function0<T> = () => T;
type Function1<T, A1> = (arg1: A1) => T;
type Function2<T, A1, A2> = (arg1: A1, arg2: A2) => T;

const foo: Function1<string, any> = () => "hi there";

我希望会出现某种错误,因为我试图断言某些0参数函数是一种带有一个参数的类型。

但是,以下代码可以很好地编译。有什么方法可以检查这些Arities是否完全匹配?

2 个答案:

答案 0 :(得分:6)

默认情况下,打字稿假定可以将具有较少参数的函数分配给将调用具有更多参数的函数,因为多余的参数将被忽略且不会带来任何危害。合理的假设:

const foo: Function1<string, any> = () => "hi there";
foo("Ignored, but why would that be a problem ?")

也就是说,在某些情况下,我们可以强制传入的函数具有与预期参数数量相同的参数数量。这种情况涉及到将函数传递给另一个函数,并且如果参数太少,则使用一些条件类型来强制执行错误:

type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;
type IsArg1Valid<T, E> = T extends (arg : infer U)=> void ? IsValidArg<U> extends true ? {} : E : E ;
function withFoo<T extends (arg: string) => any>(foo:  T & IsArg1Valid<T, "You need to pass in a function with a first argument">){

}
withFoo(()=> {}) //Type '() => void' is not assignable to type '"You need to pass in a function with a first argument"'.
withFoo(a=> console.log(a)) //ok
withFoo((a, b)=> console.log(a)) //Argument of type '(a: any, b: any) => void' is not assignable to parameter of type '(arg: string) => any'.

注意如果传递带有较少参数的函数确实是一个错误,则应该三思而行,在运行时的所有情况下这样做都是无害的。唯一的争论可能是调用者可能忽略了有用的传入参数,但这可能不足以迫使所有人始终指定所有参数。

答案 1 :(得分:5)

a

与声明但不使用其参数的函数没有什么不同:

const foo: Function1<string, any> = () => "hi there";

在Javascript中,如果不带参数调用foo_anyway,则不会出错。

因此,报告有关实际上与声明的类型兼容的函数值的错误是没有意义的。

另一方面,如果它需要更多参数,那么它将变为不兼容,并且如果您打开const foo_anyway: Function1<string, any> = (arg1: any) => "hi there"; ,则会报告错误(默认情况下,TypeScript中函数类型的兼容性规则甚至更为严格,请参见{{3 }})

--strictFunctionTypes