TypeScript递归与映射类型下多余属性警告触发方案问询
TypeScript自引用对象函数参数键检查实现方案
核心思路
要实现函数参数解构不存在的键时触发警告,关键是让TypeScript能追踪到对象的具体键集合,而非使用模糊的字符串索引签名。通过辅助函数推导对象的实际键,再为每个函数属性生成对应参数类型(仅包含该对象的所有键),就能实现精准的类型检查。
具体实现
1. 定义辅助类型
// 提取对象的所有键类型 type ObjKeys<T> = keyof T; // 生成函数参数类型:键与目标对象完全一致,值类型为指定的V type FuncParam<T, V> = { [K in ObjKeys<T>]: V }; // 定义对象属性的类型:要么是普通值T,要么是接收FuncParam的函数并返回V type SelfReferential<T, V, Obj> = { [K in ObjKeys<Obj>]: T | ((param: FuncParam<Obj, V>) => V); };
2. 编写辅助推导函数
这个函数的作用是让TypeScript自动推导对象的具体键集合,从而生成精确的参数类型:
function createSelfReferential<T, V, Obj extends Record<string, T | ((param: FuncParam<Obj, V>) => V)>>(obj: SelfReferential<T, V, Obj>): Obj { return obj; }
3. 使用示例
const example = createSelfReferential({ fieldA: 99, fieldB: ({ fieldA }) => fieldA.toUpperCase(), // 正常,fieldA是对象已有的键 fieldC: ({ fieldD }) => fieldD.toUpperCase() // 这里会触发TS警告:类型“FuncParam<{ fieldA: number; fieldB: (param: FuncParam<...>) => string; fieldC: (param: FuncParam<...>) => string; }, string>”上不存在属性“fieldD” });
原方案不可行的原因
你之前定义的SelfReferentialType使用了[key: string]字符串索引签名,这会让TypeScript认为对象可以拥有任意字符串键,无法确定具体的键集合,所以函数参数里解构任意字符串键都不会触发警告。而辅助函数能让TS先推导对象的实际键,再基于这些键生成参数类型,从而实现精准检查。
优化点(可选)
如果不想手动指定泛型参数,可以调整辅助函数的泛型顺序,让TS优先推导对象类型:
function createSelfReferential<Obj, T, V>(obj: SelfReferential<T, V, Obj>): Obj { return obj; } // 使用时无需显式传泛型,TS会自动推导所有类型 const example = createSelfReferential({ fieldA: 99, fieldB: ({ fieldA }) => fieldA.toUpperCase(), fieldC: ({ fieldD }) => fieldD.toUpperCase() // 同样会触发警告 });
内容的提问来源于stack exchange,提问作者Joseph Dvorak
相关产品推荐
相关产品推荐

