typescript - 为什么 TypeScript 有时仅将不可能的交集视为 'never' ?

标签 typescript set-intersection

TypeScript 有时会判定两种类型(如果相交)不具有任何兼容的值。这个空交集称为never,意味着您无法提供满足这两种类型的值:

type Bread = {
  shape: "loafy"
};
type Car = {
  shape: "carish"
};

// Contradiction1: Immediately resolved to 'never'
type Contradiction1 = Bread & Car;

但是,这似乎不一致。如果冲突的属性不在类型的顶层,TypeScript 会错过它并且不会按照我期望的方式运行:

// Wrap the contradicting types
type Garage = { contents: Car };
type Breadbox = { contents: Bread };

// Contradiction2: Garage & Breadbox
// Expected: Should immediately reduce to never
type Contradiction2 = Garage & Breadbox;

这是一个错误吗?为什么 TypeScript 会有这样的行为?

最佳答案

这是预期的行为,因为 TypeScript 中的属性路径可以任意深入,同时更改类型。例如,这样写是完全合法的:

declare class Boxed<T> {
  contents: T;
  doubleBoxed: Boxed<this>
};
declare const b: Boxed<string>
// m: Boxed<Boxed<Boxed<Boxed<Boxed<string>>>>>
const m = b.doubleBoxed.doubleBoxed.doubleBoxed.doubleBoxed;

因此,对于任意类型,“可以”存在实际上无限数量的属性,其中任何一个都可能具有程序中从未见过的某种新颖类型。

这对于从不来说很重要,因为你可能会写这样的东西:

// I am here to cause trouble.
type M<T, S> = T extends { nested: { nested: { nested: any } } } ?
  S :
  { el: T, nested: M<{ nested: T }, S> };

type F1 = {
  prop: M<F1, "foo">
};
type F2 = {
  prop: M<F2, "bar">
};

declare const f1: F1;
// f1.prop.nested.nested.nested: "foo"
f1.prop.nested.nested.nested;

declare const f12: F1 & F2;

// OK, infinitely
f12.prop.el.prop.el.prop.el.prop.el.prop;
// 'never' at depth 4...
f12.prop.nested.nested.nested;

确实没有办法预测您需要在什么地方寻找可能导致 never 的表达式 - M 的定义> 没有给我们任何提示;作为一个人,你必须真正理解这段代码,才能知道在哪里探索才能找到嵌套的never

事实上,如果您可以针对任意深度的属性访问“正确”解决此问题,您可以执行类似 prove/disprove the Collatz conjecture 的操作。通过构造执行算术的类型(这已经是可能的)。显然这是不可能的,因此 TypeScript 不会尝试超出生成类型的顶级属性的容易解决的情况。

关于typescript - 为什么 TypeScript 有时仅将不可能的交集视为 'never' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61902123/

相关文章:

typescript 历史js冲突

Typescript addEventListener 设置事件类型

python - 列出多个匹配实例的交集

typescript - 在 Typescript 中定义函数类型、函数接口(interface)

javascript - TypeScript - 迭代枚举时的奇怪行为

python - 在两个文件夹中查找名称首字母相同的文件

c# - lambda 中的自定义相交

c++ - 如何在 c 中对 vector<string> 进行比较和排序

javascript - 用于验证字符串格式的正则表达式 <whole-number>@<whole-number>

c++ - 推力 set_intersection 是如何工作的?