基于泛型的类型(功能参数的类型)

时间:2020-03-24 12:38:14

标签: typescript typescript-generics

我想有一个基于函数参数类型的变量类型。我尝试使用泛型,但仍然有一些错误。

interface A {
    value: string;
}

interface B {
    value: number;
}

interface extA extends A {
    id?: string;
}

interface extB extends B {
    id?: number;
}

function foo<T extends A | B>(param: T) {
    const newParam: T extends A ? extA : extB = param;

    newParam.id = param.value;

    return newParam;
}


const a = { value: "1" } as A;
const b = { value: 1 } as B;

const resultA = foo(a); // resultA is "extA" not "extA | extB"
const resultB = foo(b); // resultB is "extB" not "extA | extB"

代码已组成,但可以说明。基于功能参数param的类型,我想使用两种主要类型newParam的扩展类型。因此,如果我选择每种类型之一的参数,TS就会知道将返回哪种类型。如何实现呢?

TS Playground

1 个答案:

答案 0 :(得分:1)

如果不需要泛型,则可以在TS中使用函数重载:

function foo(param: A): extA;
function foo(param: B): extB;
function foo(param: A | B): extA | extB {
    const newParam: extA | extB = param;
    newParam.id = param.value;

    return newParam;
}

Full playground

正确检测到类型。

但是您应该注意函数的实现-返回extA | extB对于以前的重载无效的内容(开发人员可能会在实现中犯错误或添加新的重载而忘记实现)。
示例:

function foo(param: A): extA;
function foo(param: B): extB;
function foo(param: A | B): extA | extB {
    const newParam: extB = {
        value: 3,
        id: 22
    };

    return newParam; // always returned only `extB`
}

const a = { value: "1" } as A;
const b = { value: 1 } as B;

const resultA = foo(a);
const resultB = foo(b);

resultA.value // type detected as string
// (correct according to overloading) but implementation
// returns always number what is correct according to its definition
// but incorrect according to previous overload signatures - developer mistake

Playground