TypeScript中实现支持按名称索引且保留类型的泛型回调工厂
如何实现仅约束指定索引属性类型的泛型回调工厂?
你的需求完全可以实现!你最初的思路方向是对的,只是泛型约束的写法太严格了——之前的Dateable<T>要求对象的所有属性都是DateTime,但你真正需要的是只约束指定的单个属性为DateTime类型。
正确的泛型回调工厂写法
我们可以通过Record<K, DateTime>来精准约束泛型,确保对象的指定键K对应的值是DateTime,而其他属性可以是任意类型:
const compareByClosestTo = <T extends Record<K, DateTime>, K extends keyof T>( key: K, date: DateTime ) => (l: T, r: T) => Math.abs(l[key].diff(date).milliseconds) - Math.abs(r[key].diff(date).milliseconds);
为什么这个写法能满足需求?
T extends Record<K, DateTime>:表示T可以是任意对象,但必须包含K这个键,且该键对应的值类型为DateTime,其他属性无任何限制。- 调用时TypeScript会自动推导类型:比如你写
candidates.sort(compareByClosestTo("recieved", date)),TS会自动识别K为"recieved",并检查candidates中每个元素的"recieved"属性是否为DateTime类型,全程保证类型安全。
对比你后来的写法
你后续实现的sortByClosest函数是直接对数组做排序操作,虽然能工作,但复用性不如回调工厂——如果需要在多个不同数组的排序场景中使用“按指定日期属性找最近值”的逻辑,回调工厂的写法可以直接把排序函数传递给Array.sort(),灵活性更高。
验证调用示例
假设你有这样的数组:
interface Candidate { id: number; name: string; recieved: DateTime; } const candidates: Candidate[] = [/* ... */]; const targetDate = DateTime.now(); // 完全符合你的预期写法,且类型检查正常 candidates.sort(compareByClosestTo("recieved", targetDate));
这样就完美实现了你想要的“按名称索引且保留类型信息”的泛型回调工厂啦!
内容的提问来源于stack exchange,提问作者FrozenKiwi
相关产品推荐
相关产品推荐

