来自if语句的Typescript类型检测

时间:2017-10-16 09:48:18

标签: typescript type-inference

请考虑以下事项:

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

之类的东西来推断类型

1 个答案:

答案 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语句来获得答案。