首先,请注意我正在使用TypeScript 2.9.2,因为我们在等待3.1之前再次升级。
我有一个包装通过的函数的函数,返回的函数与通过的函数相同,但是添加了第一个参数和不同的返回类型。这是问题的简单再现:
interface Foo<T> {
foo: string
value: T
}
type GetFoo1<T, R> = (t: T) => Foo<R>;
type GetFooAny<R> = (...args: any[]) => Foo<R>;
type OtherFoo1<T> = (other: boolean, t: T) => Foo<void>;
type OtherFooAny = (other: boolean, ...args: any[]) => Foo<void>;
function f<T, R>(fn: GetFoo1<T, R>): OtherFoo1<T>;
function f<R>(fn: GetFooAny<R>): OtherFooAny {
return (other: boolean, ...args: any[]) => {
return {foo: 'foo', value: void 0};
};
}
const test1 = (a: string): Foo<boolean> => ({foo: 'foo', value: true});
const testAny = (a: string, b: number) => ({foo: 'foo', value: false});
// Yay
const foo1 = f(test1);
// Error
const fooAny = f(testAny);
我不确定为什么,但是除非我强制类型,否则它将永远不会基于类型选择回退实现。例如
const fooAny = f(testAny as GetFooAny<boolean>);
或
const testAny: GetFooAny<boolean> =
(a: string, b: number) => ({foo: 'foo', value: false});
const fooAny = f(testAny);
会工作的。
我遇到此麻烦的原因是我希望GetFoo*
的参数类型能够传递到OtherFoo*
。这行得通,但是我必须强制或专门添加类型的事实使我觉得自己做错了。
编辑:实际上,强制也不正确。它消除了错误,但是返回类型最终是OtherFoo1<any>
而不是OtherFooAny
。 TypeScript拒绝使用后备实现。
答案 0 :(得分:1)
TypeScript拒绝使用后备实现。
为了参与重载解析,即使签名与实现签名完全相同,也必须将签名声明为重载。
function f<T, R>(fn: GetFoo1<T, R>): OtherFoo1<T>;
function f<R>(fn: GetFooAny<R>): OtherFooAny;
function f<R>(fn: GetFooAny<R>): OtherFooAny {
return (other: boolean, ...args: any[]) => {
return {foo: 'foo', value: void 0};
};
}