TypeScript报错:Type 'boolean'无法赋值给'never'类型问题排查
TypeScript动态属性赋值的类型约束问题解决
问题场景
你定义了如下TypeScript代码,希望通过ZitroneIndexes(即keyof Zitrone)实现动态属性赋值的类型约束,但遇到了Type 'boolean' is not assignable to type 'never'.ts(2322)错误:
type ZitroneIndexes = keyof Zitrone; type Zitrone = { attr1: any, attr2: boolean, attr3: number } // 省略其他代码 objects.forEach((obj: { attr__name: keyof Zitrone; text__: any; attr__type: any; }) => { switch (obj.attr__type) { case "boolean": let attribute_name : keyof Zitrone = obj.attr__name; zitrone[attribute_name] = getBool(obj.text__); case "int": let attribute_name : keyof Zitrone = obj.attr__name; zitrone[attribute_name] = getInt(); default: console.log("object type could not be found."); } }); const getBool = (bool : string) => { return bool === 'true'; }
当ZitroneIndexes是单一类型时能正常工作,但使用包含多种类型的keyof或映射类型就报错,尝试联合类型也未解决。
问题原因
TypeScript无法自动关联obj.attr__name和obj.attr__type的类型关系:
- 你定义的obj类型中,
attr__name是keyof Zitrone(即"attr1" | "attr2" | "attr3"),attr__type是any,两者没有绑定 - 当你在
case "boolean"分支赋值boolean类型时,TS不知道attribute_name一定是Zitrone中值为boolean的键(比如attr2),它认为属性名可能是任意键,此时赋值的boolean类型无法匹配所有键对应的值类型(比如attr3是number),交集为空就会推断为never类型,导致报错
解决方案
需要用判别式联合类型让TypeScript识别attr__name和attr__type的关联关系,具体步骤如下:
1. 定义按值类型分类的键类型
先通过映射类型提取Zitrone中对应值类型的键:
type Zitrone = { attr1: any, attr2: boolean, attr3: number } // 提取值为boolean类型的键 type BooleanKeys = { [K in keyof Zitrone]: Zitrone[K] extends boolean ? K : never }[keyof Zitrone]; // 提取值为number类型的键 type NumberKeys = { [K in keyof Zitrone]: Zitrone[K] extends number ? K : never }[keyof Zitrone];
2. 定义关联的obj联合类型
把obj定义为不同类型场景的联合,让attr__type作为判别式:
type ObjType = | { attr__name: BooleanKeys; text__: string; attr__type: "boolean" } | { attr__name: NumberKeys; text__: string; attr__type: "int" } | { attr__name: keyof Zitrone; text__: any; attr__type: string };
3. 修复循环与赋值逻辑
此时switch分支中TypeScript会自动收窄类型,无需手动指定attribute_name的类型,同时要注意添加break避免case贯穿:
objects.forEach((obj: ObjType) => { switch (obj.attr__type) { case "boolean": // TS自动推断attribute_name是BooleanKeys(即"attr2") zitrone[obj.attr__name] = getBool(obj.text__); break; case "int": // TS自动推断attribute_name是NumberKeys(即"attr3") zitrone[obj.attr__name] = getInt(); break; default: console.log("object type could not be found."); } }); const getBool = (bool: string) => bool === 'true'; const getInt = () => parseInt('123'); // 示例实现
相关知识点
- 判别式联合类型:通过共同的属性(比如这里的
attr__type)作为判别式,TypeScript可以在分支中自动收窄类型,明确属性的类型关联 - 映射类型:用于遍历对象的键,根据值类型筛选或转换键类型,是处理动态键类型的常用手段
- 类型收窄:通过条件、switch等语句让TypeScript缩小变量的可能类型范围,避免never类型报错
内容的提问来源于stack exchange,提问作者Silver Sky
相关产品推荐
相关产品推荐

