如何在不使用let的情况下修改TypeScript联合类型变量的type值?
问题描述
先看这段TypeScript代码:
interface X { type: "x"; } interface Y { type: "y"; } interface Z { type: "z"; } type U = X | Y | Z; const u = { type: "x" } as U;
想要在条件判断里修改u.type的值,但两次尝试都报错:
if (u.type === "x") { // 尝试1 u.type = "y"; // error: Type '"y"' is not assignable to type '"x"'.ts(2322) // 尝试2 u = { type: "y" }; // Cannot assign to 'u' because it is a constant.ts(2588) }
问题是:不用把u改成let,有没有办法实现条件更新u.type?
解决方案
当然有,核心原因是TypeScript在u.type === "x"时会把u的类型窄化为X,此时type属性被限制为只能是"x"。下面是几种可行的方法:
方法1:给属性做类型断言
直接把要赋值的类型断言成联合类型U的type字段类型,绕开类型窄化的限制:
if (u.type === "x") { u.type = "y" as U["type"]; // 可行 }
尽量避免用
as any,虽然也能生效,但会失去TypeScript的类型检查优势。
方法2:给整个对象重新断言为联合类型U
把u临时断言回U类型,解除类型窄化的约束:
if (u.type === "x") { (u as U).type = "y"; // 可行 }
方法3:使用Object.assign
Object.assign的类型处理逻辑允许这种修改,只要新属性符合联合类型的要求:
if (u.type === "x") { Object.assign(u, { type: "y" }); // 可行 }
这三种方法都不需要把const u改成let u,因为都是修改对象的属性,而非重新赋值整个变量。
内容的提问来源于stack exchange,提问作者Martijn
相关产品推荐
相关产品推荐

