TypeScript赋值报错'string|number|boolean'不可赋值给'never'的原因及修复
TypeScript赋值错误原因与修复
错误原因
用Object.entries()遍历Foo对象时,TypeScript会把返回的键值对推断为[string, string | number | boolean]类型。哪怕你把key断言成keyof Foo、value断言成Foo[keyof Foo],TS也没法在循环的每一次迭代里,把当前key的具体类型和对应value的类型绑定起来。
举个实际的例子:循环里的key可能是"foo"(对应string类型),但value却是string | boolean | number的联合类型,TS没办法保证当前的value正好是key对应的类型。这种情况下,TS会把foo[key]的类型推断成所有Foo属性类型的交集——string & boolean & number,这三种类型没有任何重叠,结果就是never,自然会抛出赋值不兼容的错误。
修复方案
方案1:类型断言快速解决(简单但需确保逻辑正确)
直接给赋值语句加类型断言,手动告诉TS类型匹配:
foo[key] = value as Foo[typeof key];
这种方式相当于跳过TS的类型检查,适合你能100%确认逻辑没问题的场景。
方案2:泛型函数实现类型安全赋值(推荐)
把赋值逻辑抽成泛型函数,让TS能关联键和值的对应类型:
type Foo = { foo: string, bar: boolean, baz: number }; private test = () => { const foo = { foo: "bar", bar: true, baz: 1 } as Foo; // 泛型函数锁定键值类型对应关系 const setFooProp = <K extends keyof Foo>(key: K, value: Foo[K]) => { foo[key] = value; }; for (const [key, value] of Object.entries(foo)) { setFooProp(key as keyof Foo, value as Foo[keyof Foo]); } };
泛型<K extends keyof Foo>会在每次调用时确定key的具体类型,对应的value必须是该key在Foo中的类型,TS就能确认赋值是安全的。
方案3:类型守卫逐一匹配(最严谨)
如果想完全避免类型断言,可以用类型守卫逐个检查键的类型,确保值的类型匹配:
type Foo = { foo: string, bar: boolean, baz: number }; private test = () => { const foo = { foo: "bar", bar: true, baz: 1 } as Foo; Object.entries(foo).forEach(([key, value]) => { switch(key) { case "foo": foo[key] = value as string; break; case "bar": foo[key] = value as boolean; break; case "baz": foo[key] = value as number; break; } }); };
这种方式最严谨,但如果Foo的属性很多,代码会比较繁琐,适合属性数量少的场景。
内容的提问来源于stack exchange,提问作者chitzui
相关产品推荐
相关产品推荐

