Poznajemy kolejne, w zasadzie dosyć proste utility types – Pick oraz Omit. Znamy tych utilsów już dość dużo, więc raczej z kronikarskiego obowiązku o nich wspominamy.
Ok, taki interfejs mamy:
interface Todo9 {
title: string;
description: string;
completed: boolean;
}
Teraz za pomocą pick chcemy wybrać sobie konkretne pola z tego interfejsu:
type TodoPreview = Pick<Todo9, "title" | "completed">;
// type TodoPreview = {
// title: string;
// completed: boolean;
// }
Jak widać utworzyło nam typ na podstawie tamtego interfejsu, ale brane pod uwagę są tylko te pola, które zaznaczyliśmy. Tak wygląda ten typ w użyciu:
interface Todo9 {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo9, "title" | "completed">;
// type TodoPreview = {
// title: string;
// completed: boolean;
// }
const todo9: TodoPreview = {
title: "Clean room",
completed: false,
};
Ok, fajnie, ale jak ten pick działa? Cóż, sami sobie możemy go napisać:
type MyPick<T, K extends keyof T> = { [P in K]: T[P]; }
Pierwsze, co bierze, to typ T. Drugie to K, który musi być kluczem/kluczami T. I iteruje po tych kluczach i w ten sposób tworzy obiekt, którego properties to są K. I z typu T bierze T[P] czyli typy tych properties.
Może być ciężko to ogarnąć, może łatwo, z doświadczenia powiem, że po prostu dwa/trzy dni mapowanymi typami się trzeba pobawić i potem się to czyta na totalnym luzie.
Ok, sprawdźmy, czy działa:
interface Todo9 {
title: string;
description: string;
completed: boolean;
}
type MyPick<T, K extends keyof T> = { [P in K]: T[P]; }
type TodoPreview = MyPick<Todo9, "title" | "completed">;
// type TodoPreview = {
// title: string;
// completed: boolean;
// }
const todo9: TodoPreview = {
title: "Clean room",
completed: false,
};
Działa, co ma nie działać. Teraz Omit, domyślamy się już pewnie, co robi:
interface Todo9 {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Omit<Todo9, "completed">;
// type TodoPreview = {
// title: string;
// description: string;
// }
const todo9: TodoPreview = {
title: "Clean room",
description: "Clean your room!"
};
Tutaj kazaliśmy mu olać completed. Pytanie jednak, jak ten omit działa:
type MyOmit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; }
Ok, za długie, możemy to uprościć:
type MyOmit<T, K extends keyof any> = { [P in Exclude<keyof T, K>]: T[P]; }
Dobra, i co my tu mamy? T i K. T to typ, K to coś, co może być kluczem. Potem iterujemy po kluczach tylko właśnie, co my tam robimy?
Mamy Exclude, któremu przekazujemy klucze T i każemy wywalić K. Jak już mamy odsiane z kluczy T wszystkie K to iterujemy i wyciągamy z tych niepominiętych kluczy wartości T[P].
Tu warto zrozumieć, że do omit możemy przekazać klucze, których nie ma w T:
interface Todo9 {
title: string;
description: string;
completed: boolean;
}
type MyOmit<T, K extends keyof any> = { [P in Exclude<keyof T, K>]: T[P]; }
type TodoPreview = Omit<Todo9, "completed"| "createdAt"| "fullName">;
// type TodoPreview = {
// title: string;
// description: string;
// }
Natomiast wszystko działa bez zarzutu. Bo tak działa exclude:
interface Todo9 {
title: string;
description: string;
completed: boolean;
}
type Excluded = Exclude<keyof Todo9, "completed"| "createdAt"| "fullName">;
//"title" | "description"
Już to tłumaczyliśmy, ale możemy przypomnieć:
interface Todo9 {
title: string;
description: string;
completed: boolean;
}
//type Exclude<T, U> = T extends U ? never : T
type Excluded = Exclude<keyof Todo9, "completed"| "createdAt"| "fullName">;
//"title" | "description"
Chyba wszystko jasne. Do kupy zbierając:
interface Todo9 {
title: string;
description: string;
completed: boolean;
}
//type Exclude<T, U> = T extends U ? never : T
type Excluded = Exclude<keyof Todo9, "completed"| "createdAt"| "fullName">;
//"title" | "description"
type MyOmit<T, K extends keyof any> = { [P in Exclude<keyof T, K>]: T[P]; }
type TodoPreview = Omit<Todo9, "completed"| "createdAt"| "fullName">;
// type TodoPreview = {
// title: string;
// description: string;
// }
Extract działa odwrotnie, była o tym lekcja. Koniec końców, chodzi o to, abyśmy wiedzieli, jak te util types (Exclude, Extract, Omit, Pick) działają, choć umiejętność napisania ich samemu czy też zrozumienia o co chodzi po szybkim zastanowieniu się, to znak, że idziemy w dobrym kierunku i niedługo będziemy obeznani w TS.
Do następnego razu!