Takie tam proste albo i trudne ćwiczenie w TS. Piszemy funkcję pluck na kilka sposobów, analizujemy temat, rozszerzamy swoją wiedzę w TS. Zaczynajmy.
Ok, tak wygląda ta funkcja w jej pierwszej postaci:
function pluck1<T, K extends keyof T>(o: T, propertyNames: K[]): T[K][]{
return propertyNames.map((n) => o[n] );
}
Jesteśmy w stanie ogarnąć, co tu się dzieje? Jak nie, to staramy się to wypróbować:
function pluck1<T, K extends keyof T>(o: T, propertyNames: K[]): T[K][]{
return propertyNames.map((n) => o[n] );
}
const obj332 = {a:1, b: 2, c: 3};
const plucked = pluck1(obj332, ['a', 'b']);
console.log(plucked) // [1,2]
Ok, fajnie. Czym jest ten return type? Zobaczmy, czy sami potrafimy wydedukować, aplikując to, co już znamy:
type PluckRetType1 = ReturnType<typeof pluck1>
//type PluckRetType1 = any
No ten util wiele nam nie powiedział, choć to, że funkcja może zwrócić dosłownie wszystko w formie tablicy to już jakaś informacja jest. Drążymy dalej temat, to jest funkcja generyczna, czy ReturnType rozkmini nam temat, jak podamy generyczne argumenty?
type PluckRetType2 = ReturnType<typeof pluck1<{a: number, b: number, c: number}, keyof {a: number, b: number, c: number} >>
//type PluckRetType2 = number[]
Teraz podaje, że number. Ok, zmieńmy co nieco i zobaczmy co z tego wyjdzie:
type PluckRetType2 = ReturnType<typeof pluck1<{a: number, b: string, }, "a"|"b" >>
// type PluckRetType2 = (string | number)[]
Ok, czyli tablica mieszana, gdzie mogą być stringi i liczby. Dobra, to teraz pomyślmy, czym jest ten typ zwracany. Zróbmy tak: podmieńmy go na coś, co już znamy, a co, innymi słowami, opisze to, co podejrzewamy, i zobaczmy, czy będzie problem:
function pluck1<T, K extends keyof T>(o: T, propertyNames: K[]): T[keyof T][]{
return propertyNames.map((n) => o[n] );
}
const obj332 = {a:1, b: 2, c: 3};
const plucked = pluck1(obj332, ['a', 'b']);
console.log(plucked) // [1,2]
Problemu nie ma, a ten keyof już znamy. To taka sztuczka, aby właśnie z obiektu wyciągnąć typy wszystkich wartości, jakie klucze mogą zwrócić.
Znaczy – keyof T to unia kluczy. T[keyof T] to unia wartości, jakie są pod kluczami w T. Znak tablicy to tablica, to co przed [] to jej typ. Proste? Chyba tak.
Ok, a teraz jak zrobić, aby można było podawać argumenty po ludzku? Czyli po przecinku?
Takie rzeczy najbardziej rozwalają nam głowę, jak się dopiero co uczymy. Ok, oto patent:
function pluck1<T, K extends keyof T>(o: T, ...propertyNames: K[]): T[keyof T][]{
return propertyNames.map((n) => o[n] );
}
const obj332 = {a:1, b: 2, c: 3};
const plucked = pluck1(obj332, 'a', 'b');
console.log(plucked) // [1,2]
Spreada używamy na nazwie argumentu. Po drugiej stronie nie używamy. Druga strona (prawa) reprezentuje typ tych wszystkich argumentów propertyNames, do kupy.
Ok, wydłużyła się ta lekcja, reszta o pluck w następnej, bo nie chcę za bardzo przytłoczyć. Bo trochę ta składnia może namieszać we łbie, nie oszukujmy się.
Do następnego razu!