tipizare - Typescript keyof unde valoarea are tip
Încerc să scriu o funcție în Typescript care primește:
- un obiect care are cel puțin un membru de tip
X(în acest exemplu: boolean) o cheie a obiectului care indică valoarea respectivă
(de ex.
{someValue: true}-> key="someValue")
În prezent, abordarea mea este următoarea:
function myFunction<
T extends Record<K, boolean>, // the type of the object
K extends keyof T, // the key which points to X
>(
obj: T,
objKey: K,
) {
const x: boolean = obj[objKey];
}
Acest lucru funcționează atâta timp cât am nevoie ca obiectul să fie de tip T și fără tipuri suplimentare. Totuși, acum am nevoie de un obiect care să implementeze atât T (un obiect cu un membru boolean), cât și AdditionalData. Totuși, dacă înlocuiesc T extends Record<...> cu T extends Record<...> & AdditionalData, verificarea tipului, desigur, eșuează.
Soluția la care m-am gândit a fost să introduc un alt tip generic L, care include doar date din SomeInterface și să fac ca K să depindă de acesta:
function myFunction<
L extends Record<K, boolean>, // the type containing the boolean value
K extends keyof L, // the key which points to X,
T extends L & AdditionalData, // the type of the object
>(...) {}
Cu toate acestea, nici aceasta nu funcționează.
Există vreo modalitate de a forța ca valoarea indicată de o cheie să fie de un anumit tip?
EDIT: alternativ, există vreo modalitate de a exclude o valoare specifică din keyof? În acest fel, aș putea pur și simplu să exclud orice tipuri suplimentare din K...
Răspuns #1
Typescript nu raționează întotdeauna foarte bine despre tipul câmpurilor parametrilor generici. Nu sunt sigur exact ce cauzează faptul că nu recunoaște că obj[objKey] este un boolean, dar o soluție simplă este să folosești o variabilă suplimentară:
interface AdditionalData {
a: number,
b: string
}
function myFunction<
T extends Record<K, boolean> & AdditionalData, // the type of the object
K extends keyof T, // the key which points to X
>(
obj: T,
objKey: K,
) {
const o : Record<K, boolean>= obj; // assignable
const x: boolean = o[objKey]; // access works ok
}
