请考虑以下事项:
interface A {
type: 'A';
propA: 'a';
}
interface B {
type: 'B';
propB: 'b';
}
interface C {
propC: 'c';
}
type OneOfAB = A | B;
type OneOfABC = A | B | C;
Typescript可以从if语句中推断出类型:
const dataAB: OneOfAB = {} as any;
if (dataAB.type === 'A') {
console.log(dataAB.propA);
}
这个编译很好,但以下没有:
const dataABC: OneOfABC = {} as any;
if ('type' in dataABC && dataABC.type === 'A') {
console.log(dataABC.propA);
}
(Property 'type' does not exist on type 'OneOfABC'. Property 'type' does not exist on type 'C'
)。
显然,Typescript不会从'type' in dataABC
推断出dataABC的类型不是C
如何解决这个问题?我可以想到两种方式:
function isOneOfAB(data: OneOfABC): data is OneOfAB {
return 'type' in data;
}
const dataABC: OneOfABC = {} as any;
if (isOneOfAB(dataABC) && dataABC.type === 'A') {
console.log(dataABC.propA);
}
OR:
const dataABC: OneOfABC = {} as any;
if ('type' in dataABC && (dataABC as any).type === 'A') {
const dataABCcast = dataABC as A;
console.log(dataABCcast.propA);
}
在这两种情况下,我都要说打字稿比实际帮助更多。在我的用例中,有三种以上的数据类型,它们有一些重叠的属性,但也有所不同。如果我在第一个示例中使用typeguard方式,这意味着我将不得不创建许多非平凡的typeguard函数来检查属性。
我也倾向于只是将类型检查放在一起并使用any
类型。是否有任何方法可以使用类似'property' in var
答案 0 :(得分:1)
我会比你的示例更进一步,并为A
类型设置自定义类型后卫:
function isTypeA(data: any): data is A {
return 'type' in data && data.type ==='A';
}
const dataABC: OneOfABC = {} as any;
if (isTypeA(dataABC)) {
console.log(dataABC.propA);
}
这样,你可以一次性封装整个问题,而不是通过提出两个问题来获得一个if语句来获得答案。