我正在嘗試將型別資訊添加到 TypeScript 中的陣列排序函式。
這是我所追求的語法:
interface Car {
color: string;
modelYear: number;
createdDate: Date;
}
const cars: Car[] = [{
color: 'red',
modelYear: 2000,
createdDate: new Date()
}];
sortArrayBy(cars, ['createdDate'], 1); // invalid syntax, date is not a string or number, this should not compile.
sortArrayBy(cars, ['color', 'modelYear'], 1); // valid syntax, this should compile
原始代碼
export type KeysOfType<T, KeyType> = { [k in keyof T]: T[k] extends KeyType ? k : never }[keyof T];
type StringOrNumber = string | number;
export function sortArrayBy<T, TY extends KeysOfType<T, StringOrNumber>>(
arr: T[],
properties: TY[],
sortOrder: 1 | -1
): T[] {
const copy = [...arr];
const sortByProperty = (property: TY) => (a: T, b: T) => {
const aVal = a[property] as StringOrNumber; // does not compile
const aVal = a[property] as unknown as StringOrNumber; // compiles
}
return [];
}
語法像我想要的那樣作業,但我不得不as unknown在函式中使用強制轉換來編譯代碼。
我想知道,有沒有辦法縮小通用引數T(或其他想法),以便我可以洗掉演員表?
沒有演員表,完整的錯誤內容為
Conversion of type 'T[TY]' to type 'StringOrNumber' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type 'T[KeysOfType<T, StringOrNumber>]' is not comparable to type 'StringOrNumber'.
Type 'T[T[keyof T] extends StringOrNumber ? keyof T : never]' is not comparable to type 'StringOrNumber'.
Type 'T[keyof T]' is not comparable to type 'StringOrNumber'.
Type 'T[string] | T[number] | T[symbol]' is not comparable to type 'StringOrNumber'.
Type 'T[symbol]' is not comparable to type 'StringOrNumber'.
錯誤提示unknown先轉換為,這就是我這樣做的原因,我只是對其他解決方案感到好奇。
我有一個有問題的TS 操場設定。
uj5u.com熱心網友回復:
您的問題是編譯器不夠聰明,無法看到T[KeysOfType<T, V>]必須分配給Vgeneric T。有關詳細資訊,請參閱microsoft/TypeScript#30728。
相反,您可以做的是將通用物件型別約束T為Record<K, string | number>以及將鍵型別約束K為KeysOfType<T, string | number>. K(如果你不介意的話,我在這里將鍵型別稱為更傳統的鍵型別而TY不是 。)從某種意義上說,這是一個回圈且冗余的約束,但編譯器對此很滿意。當你有一個型別被T限制為Record<K, V>時,編譯器足夠聰明,可以看到它T[K]可以分配給V:
export function sortArrayByExample<
T extends Record<K, string | number>,
K extends KeysOfType<T, string | number>
>(arr: T[], keys: K[]) {
const sortByProperty = (property: K) => (a: T, b: T) => {
const aVal: StringOrNumber = a[property]; // okay
const bVal: StringOrNumber = b[property]; // okay
};
}
這T extends Record<K, string | number>是為了函式實作內部的編譯器的利益,而K extends KeysOfType<T, string | number>為了呼叫者的利益,以便他們獲得 IntelliSense 和有用的錯誤訊息:
sortArrayByExample(cars, ['createdDate']); // error
// ---------------------> ~~~~~~~~~~~~~
// Type '"createdDate"' is not assignable to type 'KeysOfType<Car, string | number>'
sortArrayByExample(cars, ['color', 'modelYear']); // okay
Playground 代碼鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/464716.html
標籤:打字稿
