如何从泛型对象中通过键获取正确的值类型?
解决TypeScript映射器中“Property 'a' does not exist on type 'TState[Key]'”错误
问题出在你的泛型定义过于宽泛,导致TypeScript无法在判断key === 'obj'时自动推断value的具体类型。原代码中TState可以是IListState的任意子类型,Key是TState的任意键,编译器无法保证当key为obj时,TState[Key]一定包含a属性。
下面是几种可行的修复方案:
方案一:简化泛型,固定关联IListState
直接移除不必要的TState泛型,让映射器明确针对IListState类型,这样当key缩小到obj时,编译器能正确识别value的类型:
interface IListState { name: string; age: number; isValid: boolean; obj: { a: number; } } // 泛型仅保留Key,绑定到IListState的键 type TChangeMapper = <Key extends keyof IListState>( key: Key, value: IListState[Key] ) => unknown; const mapper: TChangeMapper = (key, value) => { if (key === 'obj') { return value.a; // 编译器现在能正确识别value是IListState['obj'] } }; const result = mapper('obj', { a: 123 });
方案二:使用类型断言快速修复(适合简单场景)
如果需要保留原泛型结构,可以用类型断言直接告知编译器当前value的类型:
interface IListState { name: string; age: number; isValid: boolean; obj: { a: number; } } type TChangeMapper = < TState extends IListState = IListState, Key extends keyof TState = keyof TState, >( key: Key, value: TState[Key] ) => unknown; const mapper: TChangeMapper = (key, value) => { if (key === 'obj') { // 断言value为IListState['obj']类型 return (value as IListState['obj']).a; } }; const result = mapper('obj', { a: 123 });
方案三:用类型守卫做安全类型缩小(推荐复杂场景)
定义一个类型守卫函数,让编译器更安全地判断value的类型:
interface IListState { name: string; age: number; isValid: boolean; obj: { a: number; } } // 类型守卫:判断value是否为IListState['obj']类型 function isObjValue(value: unknown): value is IListState['obj'] { return typeof value === 'object' && value !== null && 'a' in value; } type TChangeMapper = <Key extends keyof IListState>( key: Key, value: IListState[Key] ) => unknown; const mapper: TChangeMapper = (key, value) => { if (key === 'obj' && isObjValue(value)) { return value.a; // 编译器能通过类型守卫确定value的类型 } }; const result = mapper('obj', { a: 123 });
内容的提问来源于stack exchange,提问作者Beardless
相关产品推荐
相关产品推荐

