Skip to content
Oskar Kowalów
LinkedInGithub

Typescript - literal inference

Typescript1 minuta czytania

W Typescript możemy trafić na błąd typu "Argument of type X is not assignable to parameter of type Y". Co to oznacza i jak to naprawić?

Typy ogólne i typy dosłowne

W Typescript mamy typy ogólne, takie jak string, number, boolean i typy dosłowne, np. "Oskar" lub 123. Naprawdę, zmienna może mieć taki dosłowny typ.

Deklarując zmienną i przypisując do niej wartość prymitywną, możemy użyć słowa kluczowego let lub const. W zależności od tego jak zadeklarujemy zmienną, będzie miała ona inny typ.

1let myName = "Oskar"; // zmienna ma typ "string"
2const myRealName = "Oskar"; // zminna ma typ "Oskar"

Dzieje się tak dlatego, że deklarując zmienną słowem kluczowym let, możemy tą zmienną nadpisać i przypisać do niej inną wartość typu string. W przypadku stałej const, nasza zmienna jest read-only i nie mamy możliwości jej nadpisania. Stałą const, z przypisaną wartością prymitywną, Typescript oznaczy typem dosłownym.

Obiekty jako const

Z obiektami jest trochę inaczej. Tworząc obiekt i przypisując go do zmiennej, przypisujemy de facto referencję do tego obiektu, a nie dokładną jego zawartość. Stąd nie ma znaczenia, czy obiekt zadeklarujemy jako let czy const, zawsze dostaniemy ogólny typ.

1declare function possibleButtonProps (color: "white" | "black", size: "big" | "small"): void;
2
3const buttonProps = {
4 color: "white", // color jest typu string
5 size: "big" // size jest typu string
6};
7
8// 💥 BOOM. Argument of type 'string' is not assignable to parameter of type '"white" | "black"'
9possibleButtonProps(buttonProps.color, buttonProps.size);

Jak to naprawić?

Zakładając, że w przyszłości nie chcemy zmieniać tego obiektu, moim zdaniem, najlepszym sposobem na to będzie oznaczenie obiektu jako as const.

1const buttonProps = {
2 color: "white",
3 size: "big"
4} as const;
5
6// ✅ OK
7possibleButtonProps(buttonProps.color, buttonProps.size);

as const działa jak const ale dla typów. Oznacza to, że właściwości tego obiektu, są oznaczone jako readonly. Podczas próby nadpisania właściwości obiektu, Typescript wyrzuci nam błąd i nie pozwoli nadpisać tej właściwości.