基于泛型字符串联合的动态字段赋值类型问题
解决TypeScript动态添加字段的类型错误问题
你遇到的核心问题是:当使用泛型Name定义动态字段时,TypeScript在循环/reduce中无法追踪单个name对应的字段类型,导致赋值时出现类型不匹配报错。以下是几种可行的解决方案,都能保持类型安全:
方案一:使用Object.assign合并属性
Object.assign的类型推导能正确识别新增属性的类型,避免直接赋值时的类型冲突:
type Extended<Base extends object, Name extends string> = Base & Record<Name, string> & Record<`${Name}Something`, boolean>; const addFields = <Base extends object, Name extends string>( obj: Base, names: ReadonlyArray<Name> ): Extended<Base, Name> => { return names.reduce((acc, name) => { return Object.assign(acc, { [name]: "test", [`${name}Something`]: true }); }, { ...obj } as Extended<Base, Name>); }; // 使用示例 const test = addFields({ x: 123 }, ["y"]); test.x; test.y; // 类型为string test.y = "test2"; // 类型检查通过 test.ySomething = false; // 类型检查通过
方案二:临时放宽累积器类型
先将累积器类型放宽为兼容所有可能的新增字段,循环赋值完成后再断言回目标类型:
type Extended<Base extends object, Name extends string> = Base & Record<Name, string> & Record<`${Name}Something`, boolean>; const addFields = <Base extends object, Name extends string>( obj: Base, names: ReadonlyArray<Name> ): Extended<Base, Name> => { let acc = { ...obj } as Base & Record<string, string | boolean>; for (const name of names) { acc[name] = "test"; acc[`${name}Something`] = true; } return acc as Extended<Base, Name>; };
这种方式更直观,循环内的赋值完全符合类型约束,外部使用时类型依然严格。
方案三:单个属性类型断言
直接为每个赋值操作指定类型,明确告诉TypeScript赋值类型符合目标要求:
type Extended<Base extends object, Name extends string> = Base & Record<Name, string> & Record<`${Name}Something`, boolean>; const addFields = <Base extends object, Name extends string>( obj: Base, names: ReadonlyArray<Name> ): Extended<Base, Name> => { return names.reduce((acc, name) => { acc[name] = "test" as Extended<Base, Name>[Name]; acc[`${name}Something`] = true as Extended<Base, Name>[`${Name}Something`]; return acc; }, { ...obj } as Extended<Base, Name>); };
以上三种方案都能解决内部类型报错问题,同时保持外部调用的类型安全——返回的对象会正确包含新增字段,且类型检查完全有效。
内容的提问来源于stack exchange,提问作者Naszos
相关产品推荐
相关产品推荐

