Kolejna ciekawa sztuczka z operatorem keyof, jaką poznamy. Myślę, że lekcja będzie ciekawa, choć krótka. Zaczynajmy.

Ok, więc taki obiekcik sobie tworzymy a w zasadzie typ:

type WithDepArr = {
    name: string;
    age: number;
    dependencyArr? : (keyof WithDepArr)[];
}

Teraz korzystamy z tego, co mamy:

let obj32: WithDepArr = {
    name: "John",
    age: 23,
    dependencyArr: ['name', 'age'],
}

No jak widać ciekawie. Nie możemy podać czegoś, co nie jest kluczem. Ok, ale co z index types?

type WithDepArr2 = {
    [K: string] : any;
    dependencyArr? : (keyof WithDepArr2)[];
};

let obj322: WithDepArr2 = {
    name: "John",
    age: 23,
    cash: 1000,
    dependencyArr: ['namee', 'cash', 'blabla'],
}

Tu jak widać błędu nie ma. Bo wnioskowanie idzie po typie, to znaczy każdy string jest ok. Number by nie przeszedł, każdy string jest valid.

Ok, spróbujmy to sobie jakoś rozłożyć:

type StringKeyObj = {
    [K: string]: any;
}

let someJane: StringKeyObj = {
    name: "Jane",
    lastName: "Doe",
    age: 22
};

Teraz zrobimy nasze utility:

type WithDepArr<T> = {
    [P in keyof T]: T[P];
} & {
    dependencyArr: (keyof T)[];
}

Ok, dalej kombinujemy:

type WithDepArr<T> = {
    [P in keyof T]: T[P];
} & {
    dependencyArr: (keyof T)[];
}

type JaneWithDependency = WithDepArr<typeof someJane>;

let someJaneDeps: JaneWithDependency = {
    name: "Jane",
    lastName: "Doe",
    age: 22,
    dependencyArr: ['name', 1, 'age', 'agee']
};

I dalej nie działa. Trudno. Przynajmniej poznaliśmy index types. Być może wymyślimy z czasem sposób, aby działało, tak czy inaczej poznaliśmy fajne zastosowanie operatora keyof, ale jak widać te typy z dynamicznymi indeksami potrafią dużo zepsuć.

Pytanie otwarte, czy opłaca się takich typów używać.