除类型函数外的重载函数从不选择后备实现(其余参数)

时间:2018-09-12 20:01:45

标签: typescript

首先,请注意我正在使用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拒绝使用后备实现。

1 个答案:

答案 0 :(得分:1)

  

TypeScript拒绝使用后备实现。

是的,this is in the FAQ

为了参与重载解析,即使签名与实现签名完全相同,也必须将签名声明为重载。

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};
    };
}