为什么打字稿不知道f1
传递“ SpecificStringObj”类型的参数时返回字符串?
interface F {
(s: AnyStringObj | SpecificStringObj): string | number;
}
interface AnyStringObj {
text: string;
}
interface SpecificStringObj {
text: "specificity";
}
const f1: F = s => {
switch (s.text) {
case "specificity":
return "s";
default:
return 1;
}
};
const stringObj: SpecificStringObj = {
text: "specificity"
};
const newStringObj: AnyStringObj = { text: f1(stringObj) };
此Typescript代码在对象的最后一行 .text
上失败,错误消息是:
[ts]
Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'. [2322]
t.tsx(6, 3): The expected type comes from property 'text' which is declared here on type 'AnyStringObj'
(property) AnyStringObj.text: string
我可以通过以下方法解决此问题:
const newStringObj: AnyStringObj = { text: f1(stringObj) as string };
我的问题是:为什么打字稿不知道自从我传递“ SpecificStringObj”以来函数将返回字符串?
其他问题:这是否适合功能请求?
答案 0 :(得分:2)
您正在寻找function overloading。
interface AnyStringObj {
text: string;
}
interface SpecificStringObj {
text: "specificity";
}
function f1(s: SpecificStringObj): string;
function f1(s: AnyStringObj): number;
function f1(s: AnyStringObj | SpecificStringObj): string | number {
switch (s.text) {
case "specificity":
return "s";
default:
return 1;
}
}
const stringObj: SpecificStringObj = {
text: "specificity"
};
const newStringObj: AnyStringObj = { text: f1(stringObj) };
答案 1 :(得分:1)
Typescript不会做这种分析之王。当试图找出f1
返回的内容时,它只会查看函数的签名。在签名中,anyStringObj
和string
之间没有明确的关系(事实是它们在参数中位于相同位置,并且返回并集并没有关系)。
要帮助编译器完成此任务,可以使用重载或条件类型:
重载版本:
interface f {
(s: specificStringObj): string;
(s: anyStringObj): number;
(s: anyStringObj | specificStringObj): string | number;
}
interface anyStringObj {
text: string;
}
interface specificStringObj {
text: "specificity";
}
const f1: f = ((s:anyStringObj | specificStringObj): string | number => {
switch (s.text) {
case "specificity":
return "s";
default:
return 1;
}
}) as f;
const stringObj: specificStringObj = {
text: "specificity"
};
const newStringObj: anyStringObj = { text: f1(stringObj) };
条件类型版本
interface f {
<T extends anyStringObj | specificStringObj>(s: T): T extends specificStringObj ? string : number;
}
interface anyStringObj {
text: string;
}
interface specificStringObj {
text: "specificity";
}
const f1: f = ((s:anyStringObj | specificStringObj): string | number => {
switch (s.text) {
case "specificity":
return "s";
default:
return 1;
}
}) as f;
const stringObj: specificStringObj = {
text: "specificity"
};
const newStringObj: anyStringObj = { text: f1(stringObj) };