对象解构可防止打字稿歧视

时间:2018-09-06 19:41:27

标签: typescript

我一直在使用带有标记的联合类型来进行打字稿辨别,并且遇到了一些奇怪的事情。如果我打开实际的对象属性,那么一切都会按预期进行。但是,如果我使用解构,打字稿会报告错误。我认为这与解构在编译时的实际工作方式有关,但我不确定。您可以在playground

上看到此示例代码
interface Foo {
  discriminate: 'FOO';
  details: string;
}

interface Bar {
  discriminate: 'BAR';
  numbers: number;
}

type FooOrBar = Foo|Bar;

const foo : Foo = {
  discriminate: 'FOO',
  details: 'Blah Blah Blah'
}

const breakTaggedUnionWithRest = ({discriminate, ...fooBar} : FooOrBar) => {
  switch(discriminate) {
    case 'FOO':
      console.log(fooBar.details);
      break;
  }
}

interface Foo2 {
  discriminate: 'FOO2';
  details: string;
}

interface Bar2 {
  discriminate: 'BAR2';
  details: number;
}

type FooOrBar2 = Foo2|Bar2;

const breakTaggedUnionWithoutRest = ({discriminate, details} : FooOrBar2) => {
  switch(discriminate) {
    case 'FOO2' : return details.toLowerCase();
  }
}

const workingExample = (fooOrBar: FooOrBar) => {
  switch(fooOrBar.discriminate) {
    case 'FOO': return fooOrBar.details;
  }
}

const workingExample2 = (fooOrBar: FooOrBar2) => {
  switch(fooOrBar.discriminate) {
    case 'FOO2': return fooOrBar.details.toString;
  }
}

1 个答案:

答案 0 :(得分:1)

如果不进行分解,则discriminator属性上的switch-case可使TypeScript缩小整个fooOrBar对象的类型并正确推断该对象上其他属性的类型宾语。这是因为TypeScript理解您正在尝试通过对象的属性来进行区分。

但是,通过解构,discriminate和其他变量(在第一个示例中为fooBar,在第二个示例中为details)彼此无关。结果,在case的TypeScript中没有推断出另一个变量的类型可能会变窄,因为switch下的变量和您尝试访问的变量在任何情况下都不相关。在这一点上。