下面这段代码在 Typescript 4.3.3 会报错:
interface SomeMethod {
(message: string, ...meta: any[]): void; // #1
(data: object): void; // #2
}
declare const foo: SomeMethod;
function bar() {
const message = 'message';
const data = { key: 'value' };
const meta = [data, data];
// (message: string, ...meta: any[]): void
foo(message, ...meta);
foo.call(null, message, data); // TS2554: expected 2 arguments but got 3
foo(message, ...meta);
foo.call(null, message, ...meta); // TS2556: A spread argument must either have a tuple type or be passed to a rest parameter.
// (data: object): void
foo(data);
foo.call(null, data); // #3
}
如果交换 #1
和 #2
两行,就会变成 #3
报错:TS2345: Argument of type '{ key: string; }' is not assignable to parameter of type 'string'.
。
似乎 Typescript 在推断 Function.call
的参数类型时只考虑了最后一个重载?
1
gyang1111 2021-06-17 16:27:37 +08:00 1
看着确实不能自动推断,call 类型提示是 call<T, A extends any[], R>(this: (this: T, ...args: A) => R, thisArg: T, ...args: A): R;
需要在调用 call 的时候显式指明用的哪个重载,也就是<T, A extends any[], R> 这个部分,分别对应 this 的 type,参数的 type,和返回值的 type 写成这样就不会报错了 foo.call<null, [string, ...any], void>(null, message, data); foo.call<null, [string, ...any], void>(null, message, ...meta); |