繁体   English   中英

具有 typescript 类型的索引参数的泛型

[英]Generic with indexed argument of type in typescript

我想要一个通用的,我可以在保留输入的同时按名称索引。 能够编写以下代码会很有用:

candidates.sort(compareByClosestTo("recieved", date))

我感觉很接近,但似乎无法完成这个

// generic comparison fn with index
type Dateable<T> = {
  [P in keyof T]: DateTime
};
const compareByClosestTo = <T extends Dateable<T>>(key: keyof T, date: DateTime) => 
  (l: T, r: T) => Math.abs(l[key].diff(date).milliseconds) - Math.abs(r[key].diff(date).milliseconds)

游乐场链接

但是这会产生错误,因为它要求所有参数都是 DateTime 类型。 有没有办法简单地限制 T[key] 的类型?

编辑

发布此消息 5 分钟后,我在这里遇到了一个提示,导致我:

function sortByClosest<K extends string>(data: Record<K, DateTime>[], key: K, date: DateTime): void {
  data.sort((l, r) => 
    Math.abs(l[key].diff(date).milliseconds) - Math.abs(r[key].diff(date).milliseconds))
}

但是,我想保持开放状态,因为我真的很想知道如何计算回调工厂的类型化通用索引(即,顶级 forms 可能吗?)

我认为您原来的compareByClosestTo() function 的主要问题是T没有好的推理站点 key参数的类型为keyof T 如果您为key传入"foo" ,则需要编译器推断类型T ,其中"foo"是其键之一。 编译器可能会推断出{foo: DateTime} ,具体取决于您如何使用它,或者它可能会放弃并推断出类似{foo: any}甚至{[k: string]: any}的东西。 您唯一可以期望编译器可靠地从"foo"类型的值推断出的是字符串"foo"本身。

为此,让我们放弃T extends Dateable<T> ,而是看看K extends PropertyKey 然后我们可以用K来表示T :在这种情况下, { [P in K]: DateTime }等价于Record<K, DateTime> (使用Record实用程序类型):

const compareByClosestTo = <K extends PropertyKey>(key: K, date: DateTime) =>
  (l: { [P in K]: DateTime }, r: { [P in K]: DateTime }) =>
    Math.abs(l[key].diff(date).milliseconds) - Math.abs(r[key].diff(date).milliseconds);

让我们看看当我们调用它时会发生什么:

const compareFn = compareByClosestTo("recieved", DateTime.local());
/* const compareFn: (l: {
    recieved: DateTime;
}, r: {
    recieved: DateTime;
}) => number */

在这里, K被推断为"received" ,结果比较 function 是我们想要的{received: DateTime}类型。 因此,以下两个sort()调用都有效:

const works = dates.map(dt => ({ recieved: dt }))
  .sort(compareByClosestTo("recieved", DateTime.local()))

const stillWorks = dates.map((dt, i) => ({ recieved: dt, index: i }))
  .sort(compareByClosestTo("recieved", DateTime.local()))

因为您正在排序的每个 arrays 都有可分配给{received: DateTime}的元素。

Playground 代码链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM