如何让TypeScript识别正确索引键?解决类型赋值报错问题
解决TypeScript中索引赋值的类型不匹配问题
先看你的原代码:
type Type = { aa: string; bb: number; }; const keys = ['aa', 'bb'] as (keyof Type)[]; const target = {} as { [Key in keyof Type]: Type[Key]; }; const source: Type = { aa: 'aa', bb: 123 }; keys.forEach((key) => { const s = source[key]; // string | number const t = target[key]; // string | number // 报错:Type 'string | number' is not assignable to type 'never' target[key] = source[key]; });
报错原因
TypeScript处理联合类型索引时,无法跟踪每次迭代中key的具体类型——它只知道key是'aa' | 'bb',因此source[key]的类型是string | number。而赋值时,TS会要求值的类型能匹配所有可能的target[key]类型,也就是取string和number的交集,结果是never,所以触发报错。
解决方案:用泛型函数保留类型关联
要让TypeScript识别key和对应值的类型绑定关系,可以用泛型函数遍历键,这样每次迭代的key会被推断为keyof Type的单个子类型,而非联合类型:
type Type = { aa: string; bb: number; }; const keys = ['aa', 'bb'] as (keyof Type)[]; const target = {} as { [Key in keyof Type]: Type[Key] }; const source: Type = { aa: 'aa', bb: 123 }; // 泛型遍历函数,保留单个key的类型信息 function iterateKeys<T>(keys: Array<keyof T>, callback: <K extends keyof T>(key: K) => void) { keys.forEach(key => callback(key as K)); } // 调用泛型函数遍历赋值 iterateKeys<Type>(keys, (key) => { target[key] = source[key]; // 类型匹配,无报错 });
简化方案:直接使用Object.assign
如果你的需求只是把source的所有属性复制到target,可以直接用Object.assign,它能自动处理类型匹配:
Object.assign(target, source); // 无类型报错,直接完成赋值
原理说明
泛型函数中的K extends keyof T会让TypeScript为每个迭代的key单独推断具体类型(比如第一次是'aa',第二次是'bb'),这样source[key]和target[key]的类型会被精确匹配,避免了联合类型导致的交集推断问题。
内容的提问来源于stack exchange,提问作者Guichi
相关产品推荐
相关产品推荐

