我正在尝试创建一个函数,其参数可以是两种类型之一。然后,该函数可以调用另一个函数。但是,我收到一条错误消息。您可以在下面看到脚本和屏幕截图。如何编写此函数,使其可以接受两种类型之一的参数?谢谢!
interface A {
a: string;
title: string,
}
interface B {
b: number;
title: string;
}
const alpha = (data: A) => data.a;
const beta = (data: B) => data.b;
const foo = (data: A | B) => {
if (data.title === 'a') {
return alpha(data); // Message: "Argument type A | B is not assignable to type A"
}
if (data.title === 'b') {
return beta(data); // Message: "Argument type A | B is not assignable to type B"
}
};
答案 0 :(得分:2)
请尝试在参数上使用type assertions(如强制转换),以便在确定类型后,编译器(和IDE)会将其视为适当的类型。
interface A {
a: string;
title: string,
}
interface B {
b: number;
title: string;
}
const alpha = (data: A) => data.a;
const beta = (data: B) => data.b;
const foo = (data: A | B) => {
if (data.title === 'a') {
return alpha(<A>data);
}
if (data.title === 'b') {
return beta(<B>data);
}
};
类型断言是一种告诉编译器“相信我,我知道我在做什么”的方法。类型断言就像其他语言中的类型转换一样,但是不执行任何特殊的数据检查或重组。它对运行时间没有影响,仅由编译器使用。 TypeScript假定您(程序员)已经执行了所需的任何特殊检查。
答案 1 :(得分:1)
您需要一个类型保护,它会告诉TS A
对象的标题等于a
,而B
对象的标题则等于b
:
const isA = (x: A | B): x is A => x.title === 'a';
const isB = (x: A | B): x is B => x.title === 'b';
然后:
const foo = (data: A | B): any => {
if (isA(data)) {
return alpha(data);
}
if (isB(data)) {
return beta(data);
}
};
一个更好的选择是使区分值(a
和b
)成为类型而不是字符串:
interface A1 {
a: string;
title: 'a',
}
interface B1 {
b: number;
title: 'b';
}
然后,您可以简单地使用switch
作为类型防护:
const foo1 = (data: A1 | B1): any => {
switch (data.title) {
case 'a': return alpha(data);
case 'b': return beta(data);
}
};
答案 2 :(得分:1)
问题在于打字稿不知道title === 'a'
表示数据类型为a
。幸运的是,您可以提供一个更窄的类型而不是string
来帮助打字稿。
interface A {
a: string;
title: 'a' ; // title can now be 'a' only, not any other string.
}
interface B {
b: number;
title: 'b' ; // title can now be 'b' only, not any other string.
}
答案 3 :(得分:-7)
请使用any
。
const foo = (data: any) => {
if (data.title === 'a' && checkA(data)) {
return alpha(data);
}
if (data.title === 'b' && checkB(data)) {
return beta(data);
}
};
然后通过创建自己的函数来检查接口类型。
function checkA(obj: any) {
return 'a' in obj;
}
function checkB(obj: any) {
return 'b' in obj;
}