为何TypeScript中[1 | 2]不是[1 | []] | [2 | []]的子类型?
TypeScript元组联合类型赋值报错原因及无断言解决办法
问题场景
我有一个API,输入是元素为联合类型的元组([1 | 2]),需要将其赋值给元组的联合类型。多数场景下该操作可行,但特定场景会触发类型错误。
// 正常通过 (x: [1 | 2]): [1] | [2] => x; (x: [1 | 2]): [1 | 11] | [2 | 22] => x; (x: [1 | 2]): [1 | []] | [2 | 22] => x; // 报错 (x: [1 | 2]): [1 | []] | [2 | []] => x;
第四个示例的报错信息:
Type '[1 | 2]' is not assignable to type '[1 | []] | [2 | []]'. Type '[1 | 2]' is not assignable to type '[1 | []]'. Type '1 | 2' is not assignable to type '1 | []'. Type '2' is not assignable to type '1 | []'.
报错原因
TypeScript在检查联合类型兼容性时,要求输入类型必须能被联合类型的至少一个分支完全兼容。
前三个示例中,输入元组的元素
1 | 2总能找到返回类型分支中的匹配项:- 第一个返回类型
[1] | [2]:1匹配[1],2匹配[2]; - 第二个返回类型
[1 | 11] | [2 | 22]:1匹配[1 | 11],2匹配[2 | 22]; - 第三个返回类型
[1 | []] | [2 | 22]:1匹配[1 | []],2匹配[2 | 22]。
- 第一个返回类型
第四个示例的返回类型
[1 | []] | [2 | []]:- 输入元素
2无法匹配第一个分支[1 | []]的元素类型1 | []; - 输入元素
1无法匹配第二个分支[2 | []]的元素类型2 | [];
TypeScript无法确定输入的具体值属于哪个分支,因此抛出类型不兼容错误。
- 输入元素
无需类型断言的解决办法
方法1:使用泛型让类型精确推导
通过泛型捕获输入元组的具体元素类型,让TypeScript自动匹配对应的返回分支:
const fn = <T extends 1 | 2>(x: [T]): [T | []] => x; // 调用时: fn([1]); // 返回类型为 [1 | []] fn([2]); // 返回类型为 [2 | []] fn(Math.random() > 0.5 ? [1] : [2]); // 返回类型为 [1 | []] | [2 | []]
方法2:调整输入类型为元组联合
将输入类型从[1 | 2]改为元组的联合类型[1] | [2],让每个输入分支都能匹配返回类型的对应分支:
(x: [1] | [2]): [1 | []] | [2 | []] => x; // 正常通过
方法3:重构返回类型结构
如果业务逻辑允许,将返回类型调整为([1] | [2]) | [[]],把元素为[]的情况单独作为一个分支,这样输入的[1 | 2]能匹配到([1] | [2])分支:
(x: [1 | 2]): ([1] | [2]) | [[]] => x; // 正常通过
内容的提问来源于stack exchange,提问作者vijrox
相关产品推荐
相关产品推荐

