我想有一个基于函数参数类型的变量类型。我尝试使用泛型,但仍然有一些错误。
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就会知道将返回哪种类型。如何实现呢?
答案 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;
}
正确检测到类型。
但是您应该注意函数的实现-返回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