Svi*_*ish 1 generics typescript keyof
我有这个简单的函数可以按日期对对象进行排序。但目前我必须在进行比较之前检查该字段是否实际上是日期。在这种情况下,有没有办法限制K只允许某种类型的密钥Date?
const compareDate = <T, K extends keyof T>(key: K) => (x: T, y: T) => {
const v = x[key];
const w = y[key];
return v instanceof Date && w instanceof Date ? v.getTime() - w.getTime() : 0;
};
list.sort(compareDate('dateField'));
Run Code Online (Sandbox Code Playgroud)
我想要的是:
const compareDate = <T, K extends ???>(key: K) => (x: T, y: T) => {
// ts should know and only allow x[key] and y[key] to be of type Date here:
return x[key].getTime() - y[key].getTime();
}
const list = [{a: 1, b: 'foo', c: new Date}];
list.sort(compareDate('a')); // <-- ts should refuse this
list.sort(compareDate('b')); // <-- ts should refuse this
list.sort(compareDate('c')); // <-- ts should allow this
Run Code Online (Sandbox Code Playgroud)
有没有办法在 Typescript 中表达这一点
您可以使用映射类型来获取Date某个类型的所有属性:
type DateProps<T> = ({ [P in keyof T]: T[P] extends Date ? P : never })[keyof T];
Run Code Online (Sandbox Code Playgroud)
然后用它代替keyof T:
const compareDate = <T extends Record<K, Date>, K extends DateProps<T>>(key: K) => (x: T, y: T) => {
return x[key].getTime() - x[key].getTime();
};
Run Code Online (Sandbox Code Playgroud)
借用Record@ford04 的想法,我们甚至可以确保 TypeScript 知道x[key]和的类型y[key]。这意味着instanceof函数内部不需要进行检查或转换。