实现类Lodash的Iteratee类型时遇TypeScript类型赋值错误求助
解决TypeScript中Iteratee类型赋值错误问题
错误原因
TypeScript无法在泛型上下文里自动推断T[KeysCorrespondingToValueType<T, number>]必然是number类型。尽管我们的KeysCorrespondingToValueType类型逻辑上已经筛选出了值为number的对象键,但编译器无法回溯该类型定义的约束关系,因此无法确认item[iteratee]的类型符合返回值要求。
解决方案
方案1:使用类型断言(简洁高效)
由于Iteratee<T, number>已经约束了:要么是返回number的函数,要么是对应值为number的对象键,因此可以安全地对item[iteratee]做类型断言,告诉编译器该值确实是number:
type KeysCorrespondingToValueType<T, V> = { [K in keyof T]-?: T[K] extends V ? K : never; }[keyof T]; type Iteratee<T, V> = KeysCorrespondingToValueType<T, V> | ((item: T) => V); function getNumericValueFromIteratee<T>( item: T, iteratee: Iteratee<T, number> ): number { return typeof iteratee === 'function' ? iteratee(item) : item[iteratee] as number; }
方案2:拆分泛型参数(类型更严谨)
引入额外的泛型参数K明确键的类型,让编译器直接关联键与对应属性值的类型约束,无需断言:
type KeysCorrespondingToValueType<T, V> = { [K in keyof T]-?: T[K] extends V ? K : never; }[keyof T]; type Iteratee<T, V, K extends KeysCorrespondingToValueType<T, V>> = K | ((item: T) => V); function getNumericValueFromIteratee<T, K extends KeysCorrespondingToValueType<T, number>>( item: T, iteratee: Iteratee<T, number, K> ): number { return typeof iteratee === 'function' ? iteratee(item) : item[iteratee]; }
方案3:自定义类型守卫(带运行时检查)
如果需要额外的运行时验证,可以定义类型守卫函数,确保键对应的属性值类型符合要求:
type KeysCorrespondingToValueType<T, V> = { [K in keyof T]-?: T[K] extends V ? K : never; }[keyof T]; type Iteratee<T, V> = KeysCorrespondingToValueType<T, V> | ((item: T) => V); function isKeyOfValueType<T, V>(item: T, key: keyof T): key is KeysCorrespondingToValueType<T, V> { return typeof item[key] === typeof ({} as V); } function getNumericValueFromIteratee<T>( item: T, iteratee: Iteratee<T, number> ): number { if (typeof iteratee === 'function') { return iteratee(item); } else if (isKeyOfValueType<T, number>(item, iteratee)) { return item[iteratee]; } throw new Error('Invalid iteratee: must be a numeric property key or number-returning function'); }
内容的提问来源于stack exchange,提问作者Christopher Fimbel
相关产品推荐
相关产品推荐

