我正在嘗試創建一個型別安全的型別化比較器函式,以便我確定我總是使用現有值進行排序到目前為止我已經完成了以下操作:
export enum SortDirection {
ASCENDING = "ASCENDING",
DESCENDING = "DESCENDING",
}
/**
* Sorts in place Array of objects
* @param path path to numeric value
* @param direction the way that numeric values will be evaluated
* @returns the sorted array
*/
export const sortByNumeric = <T>(path: Array<keyof T>, direction = SortDirection.ASCENDING) => <K extends Record<keyof T, any>>(current: K, next: K) => {
const extractedA = path.reduce((acc, k) => acc[k], current);
const extractedB = path.reduce((acc, k) => acc[k], next);
return direction === SortDirection.ASCENDING ? extractedA - extractedB : extractedB - extractedA;
}
let source = [
{
name: 'Jon',
age: 20,
father: {
name: 'Jon Senior',
age: 60,
otherProp: 100
}
},
{
name: 'Gabriel',
age: 25,
father: {
name: 'Jon Senior',
age: 80,
otherProp: 20
}
}
];
source.sort(sortByNumeric(['age']));
該函式在單個屬性上作業正常,但它不能像這樣使用嵌套路徑:
source.sort(sortByNumeric(['father' , 'otherProp']));
// Here this will throw an error that the prop doesn't exits, while this is actually a valid property
或者
source.sort(sortByNumeric(['age' , 'father']));
// Here there will be no error, while at the same time this is invalid value as there is no key for the 'father'
我確定我在泛型方面做錯了,但我不知道如何以及在這里修復什么,任何指導將不勝感激。
uj5u.com熱心網友回復:
輸入任意嵌套的鍵是可能的,但并不簡單。這取決于您希望該型別的行為準確程度,但這種型別的可能實作是:
export type NumericKeyPath<T> =
[T] extends [number] ? []
: [T] extends [object] ? NumericKeyPathProperty<T, keyof T>
: never;
type NumericKeyPathProperty<T, Key extends keyof T> =
Key extends (string | number) ? [ Key, ...NumericKeyPath<T[Key]> ]
: never;
type Test = NumericKeyPath<{ name: string; age: number; father: { name: string; age: number; otherProp: number } }>;
// type Test = ["age"] | ["father", "age"] | ["father", "otherProp"]
與您的比較器功能一起使用:
export const sortByNumeric = <T>(path: NumericKeyPath<T>, direction = SortDirection.ASCENDING) => (current: T, next: T) => {
// the below casts could be done more precisely
const extractedA = (path as string[]).reduce((acc: any, k) => acc[k], current);
const extractedB = (path as string[]).reduce((acc: any, k) => acc[k], next);
return direction === SortDirection.ASCENDING ? extractedA - extractedB : extractedB - extractedA;
}
let source = [
{
name: 'Jon',
age: 20,
father: {
name: 'Jon Senior',
age: 60,
otherProp: 100
}
},
{
name: 'Gabriel',
age: 25,
father: {
name: 'Jon Senior',
age: 80,
otherProp: 20
}
}
];
source.sort(sortByNumeric(['age']));
// Works
source.sort(sortByNumeric(['father' , 'otherProp']));
// Works
source.sort(sortByNumeric(['age' , 'father']));
// Error
游樂場鏈接
請注意,由于這似乎是該函式的意圖,因此我撰寫了 NumericKeyPath 以僅允許指向數值的路徑。相關的行是[T] extends [number] ? [],例如,如果您還想允許字串值,您可以將其更改為[T] extends [number | string] ? [].
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/364353.html
標籤:打字稿
上一篇:通過減少和陣列回傳物件陣列
下一篇:打字稿動態訪問物件
