Typescript keyof generic ȘI extinde un tip
Având următoarea interfață:
interface Payload {
value1: number;
value2: string;
}
Vreau să creez o funcție care acceptă Payload[] și doar cheile din Payload care extind number. Ceva de genul acesta:
function F<T, K extends keyof T, T[K] extends number>(arr: T[], property: K) {
//
}
function foo(payloads: Payload[]) {
F(payloads, "value1"); // should work
F(payloads, "value2"); // should not work because value2 is a string
F(payloads, "value3"); // should not work because value3 not in Payload[]
}
Vezi locul de joacă
Răspuns #1
Am reușit să fac asta să funcționeze folosind un tip mapat care păstrează doar proprietățile number și number | undefined:
interface Payload {
value1: number;
value2: string;
value3?: number;
value4?: string;
}
type NumberOnly<T> = {
// Doesn't allow `number | undefined` if `strictNullChecks` is enabled
//[key in keyof T as T[key] extends number ? key : never]: T[key];
// This will always allow `number | undefined` on top of just `number`
[key in keyof T as T[key] extends number | undefined ? key : never]: T[key];
};
function F<T extends NumberOnly<any>, K extends keyof NumberOnly<T>>(arr: T[], property: K) {
const value = arr[0][property];
return value;
}
function foo(payloads: Payload[]) {
F(payloads, "value1"); // should work
F(payloads, "value2"); // should not work because value2 is a string
F(payloads, "value3"); // should work (you can filter undefined if you want)
F(payloads, "value4"); // should not work because value4 is a string
F(payloads, "value5"); // should not work because value5 not in Payload[]
}
din punct de vedere tehnic ar accepta de asemenea value5: undefined, dar nu de exemplu value5: string | undefined, un caz limită care nu ar trebui să conteze cu adevărat.
Acceptă doar value1 și value3:
bazat pe acest răspuns folosind o caracteristică TypeScript 4.1
