这些都是真的:
type A = [boolean | string] extends [boolean] | [string] ? true : false // true
type B = [number | boolean] extends [number] | [boolean] ? true : false // true
type C = [1 | string] extends [1] | [string] ? true : false // true
Run Code Online (Sandbox Code Playgroud)
但这是错误的:
type D = [number | string] extends [number] | [string] ? true : false // false
Run Code Online (Sandbox Code Playgroud)
false?在 TypeScript 4.0 之前,所有这些条件类型的计算结果均为false. 这里的问题与编译器如何以不同的方式处理具有联合类型属性的对象类型有关,当所讨论的联合被视为或不被视为可区分联合的判别式的类型时。
由于 TypeScript 3.2 引入了对非单位类型作为判别式的支持,只要联合的某些公共成员具有文字类型(或此类类型的联合)的属性,联合就可以是可判别联合。
类型boolean | string和number | boolean是可接受的判别属性,因为boolean是 union 的简写true | false,其中每个都是文字类型。 1 | string也是一个可接受的判别式,因为1是文字类型。另一方面, number | string不是可接受的判别类型,因为 和number都不string是文字类型。
一般来说,TypeScript 不考虑具有可分配给对象类型联合的联合类型属性的对象类型。也就是说,联合通常不会从属性向上传播到顶级对象:
const x: { a: RegExp | Date } = { a: Math.random() < 0.5 ? /abc/ : new Date() };
const y: { a: RegExp } | { a: Date } = x; // error!
Run Code Online (Sandbox Code Playgroud)
这种行为可能很烦人,尤其是在您尝试分配给的类型是受歧视联合的情况下。因此,TypeScript 3.5通过microsoft/TypeScript#30779引入了对“更智能”联合类型检查的支持,只要目标类型是可区分联合,您就可以执行此类分配。因此,从 TypeScript 3.5 开始,以下分配有效:
const v: { a: RegExp | "abc" } = { a: Math.random() < 0.5 ? /abc/ : "abc" };
const w: { a: RegExp } | { a: "abc" } = v; // error in TS3.4-, okay in TS3.5+
Run Code Online (Sandbox Code Playgroud)
由于"abc"是文字类型,因此 的类型w是可区分联合,因此接受赋值。
从 TypeScript 3.5 到 TypeScript 3.9,这些条件类型仍然全部计算为false,因为可分配性的这种变化并未完全反映在类型系统中,例如当您编写条件类型时。对此问题的修复microsoft/TypeScript#39393随 TypeScript 4.0 一起发布。现在,类型系统还发现具有联合属性的对象可以分配给适当的可区分联合:
type A = [boolean | string] extends [boolean] | [string] ? true : false
// false in TS3.9-, true in TS4.0+
type B = [number | boolean] extends [number] | [boolean] ? true : false
// false in TS3.9-, true in TS4.0+
type C = [1 | string] extends [1] | [string] ? true : false
// false in TS3.9-, true in TS4.0+
type D = [number | string] extends [number] | [string] ? true : false
// false
Run Code Online (Sandbox Code Playgroud)
像 之类的单元组[X]与 之类的对象类型类似{0: X},因此[X] | [Y]if is 是可判别并集{0: X} | {0: Y}。由于boolean | string和number | boolean是1 | string判别类型,因此赋值成功。由于number | string不是判别类型,因此分配失败。
| 归档时间: |
|
| 查看次数: |
132 次 |
| 最近记录: |