TypeScript中字面量类型与{}组成联合类型为何不会被拓宽?
问题核心原因:TypeScript联合类型的化简规则并非完全基于赋值兼容性,而是有明确的触发条件
首先先明确联合类型化简的基础规则:只有当联合中的某一成员是其他所有成员的同类型族直系超类型,或者是any、unknown这类全局顶级类型时,才会自动合并化简为该超类型。
我们逐个看三个示例的情况:
Test1 = "a" | "b" | string:"a"、"b"都属于字符串字面量类型,是string的直系子类型,同属原始字符串类型族,所以直接被超类型string吸收,最终化简为string。Test2 = "a" | "b" | any:any是TypeScript的全局顶级类型,和任何类型组成联合都会直接覆盖所有其他成员,所以最终化简为any。Test3 = "a" | "b" | {}:这里的矛盾点来自于对{}类型的认知偏差:- 首先
{}确实兼容所有非空值的赋值,这是结构层面的兼容,不是类型层级上的直系超类型关系。"a"、"b"属于原始字符串类型族,{}属于对象类型族,二者不在同一条类型继承链上。 - TypeScript的联合化简规则不会跨类型族仅靠结构兼容就做合并,所以最终会保留所有类型成员,不会被
{}吸收。
- 首先
我们可以用一个简单的测试验证这个规则:
type Test = 1 | number | {} // 化简结果为 number | {},1被同类型族的超类型number吸收,但number和{}不会合并
补充说明:你感觉到的直觉偏差,本质是把「赋值兼容性」和「联合类型化简规则」划了等号,二者在TS的类型系统里是两套不完全重合的逻辑,赋值兼容不代表一定会触发联合类型的合并化简。
内容的提问来源于stack exchange,提问作者Jan
相关产品推荐
相关产品推荐

