TypeScript报错:Type 'number'无法赋值给'never'类型问题求助
解决TypeScript中“Type 'number' is not assignable to type 'never'”报错
你猜的没错,问题根源就是接口DetailedRankings里同时存在string和number类型的属性。
当你用keyof DetailedRankings作为category的参数类型时,这个参数可能指向name、category这类值为string的属性,也可能指向show_id、story这类值为number的属性。你把number类型的value_number赋值给obj[category]时,TypeScript会做严格的类型检查:它会取所有可能属性类型的交集,而string和number的交集是never,所以就出现了这个报错。
下面是几种可行的解决方法:
方案一:缩小参数类型范围(最推荐)
定义一个类型,只提取DetailedRankings中值为number的属性键,让category只能接收这些键:
export interface DetailedRankings { show_id: number; name: string; category: string; episodes: number; story?: number; characters?: number; overall?: number; } // 提取对象中值为number类型的键 type NumericKeysOf<T> = { [K in keyof T]: T[K] extends number ? K : never }[keyof T]; function handleInputChange( category: NumericKeysOf<DetailedRankings>, event: string, index: number ) { const value_number: number = parseFloat(event); let list: DetailedRankings[] = [...detailed_ranks]; let obj: DetailedRankings = list[index]; obj[category] = value_number; // 不再报错 }
这种方式能在编译阶段就阻止传入name、category这类不匹配的键,类型安全性最高。
方案二:使用类型守卫做运行时判断
如果需要保留category接收所有键的灵活性,但只在对应number属性时赋值,可以用类型守卫:
export interface DetailedRankings { show_id: number; name: string; category: string; episodes: number; story?: number; characters?: number; overall?: number; } // 预先定义所有number类型属性的键集合 const numericPropertyKeys = new Set<string>([ 'show_id', 'episodes', 'story', 'characters', 'overall' ]); function handleInputChange( category: keyof DetailedRankings, event: string, index: number ) { const value_number: number = parseFloat(event); let list: DetailedRankings[] = [...detailed_ranks]; let obj: DetailedRankings = list[index]; // 判断当前category是否属于number属性的键 if (numericPropertyKeys.has(category as string)) { obj[category as keyof Pick<DetailedRankings, 'show_id' | 'episodes' | 'story' | 'characters' | 'overall'>] = value_number; } }
这种方式需要维护numericPropertyKeys集合,当接口修改时要同步更新,但保留了参数的灵活性。
方案三:类型断言(不推荐,仅临时应急)
如果你能100%确保传入的category一定是number属性的键,可以用类型断言跳过检查:
function handleInputChange(category: keyof DetailedRankings, event: string, index: number) { const value_number: number = parseFloat(event); let list: DetailedRankings[] = [...detailed_ranks]; let obj: DetailedRankings = list[index]; // 断言category指向number类型的属性 obj[category as 'show_id' | 'episodes' | 'story' | 'characters' | 'overall'] = value_number; }
这种方式会绕过TypeScript的类型检查,一旦传入错误的键,运行时可能出问题,不建议长期使用。
内容的提问来源于stack exchange,提问作者Harold
相关产品推荐
相关产品推荐

