TypeScript 可以通过 "extracted" 布尔逻辑推断可区分联合的类型吗?

Can TypeScript infer type of a discriminated union via "extracted" boolean logic?

我使用受歧视工会 (DU) 的频率更高,并且开始爱上它们。但是,我确实有一个问题,我似乎无法解决。如果为 DU 内联布尔检查,则可以依靠 TypeScript (TS) 自动为您推断类型。但是,如果提取布尔检查,TS 将无法再缩小到 DU 的特定子类型。我知道类型保护,但我想知道为什么编译器不支持提取的在线检查,特别是。

这是已知的限制吗?我应该提交 bug/feature 请求吗?

此处示例(带 TypeScript Playground Link):

type A = { type: "A"; foo: number };
type B = { type: "B"; bar: string };
type DU = A | B;

const checkIt = (it: DU) => {
  const extractedCheck = it.type === "A";

  if (extractedCheck) {
    // it does not get narrowed
    console.log(it.foo); // Error: Property 'foo' does not exist on type 'DU'.
  }

  if (it.type === "A") {
    // but this is fine
    console.log(it.foo);
  }
};

目前没有@jcalz 提到的,但是有一个最小的解决方法,您可以随时应用它来解决这个问题。

诀窍是使 extractCheck 成为 returns 类型谓词 .
的函数 (参考https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards

以下是一个工作示例:

type A = { type: "A"; foo: number };
type B = { type: "B"; bar: string };
type DU = A | B;

const checkIt = (it: DU) => {
  // Make `extractCheck` a function 
  const extractedCheck = (it: DU): it is A => it.type === "A";

  if (extractedCheck(it)) {
    console.log(it.foo);  // No error
  }
};

TS4.4 更新:

TypeScript 4.4 将支持将类型保护的结果保存到 const,如 microsoft/TypeScript#44730 中所实现的。此时,您的代码示例将正常工作:

const checkIt = (it: DU) => {
  const extractedCheck = it.type === "A";

  if (extractedCheck) {
    console.log(it.foo); // okay
  }

};

Playground link to code


TS4.3 及以下版本的答案:

microsoft/TypeScript#12184 to allow such type guard results to be "saved" into a named value to be used later. The request is open but listed as "revisit" because there's no obvious way to implement it in a performant way. The word from the lead architect of the language 有一个现有的功能请求是:

This would require us to track what effects a particular value for one variable implies for other variables, which would add a good deal of complexity (and associated performance penalty) to the control flow analyzer. Still, we'll keep it as a suggestion.

因此,不幸的是,我不希望很快在该语言中看到这样的功能。


我的建议是继续使用内联类型检查。如果你有更复杂的类型保护情况,那么做一个 user-defined type guard function 可能是值得的,但我不认为这是对你的示例代码中案例的改进。


好的,希望对您有所帮助;祝你好运!