TypeScript: wybrane właściwości opcjonalne z częściowym i pominięciem
Gdy używasz narzędzia Partial
do typu, wszystkie właściwości typu stają się opcjonalne. Zobaczmy, jak możemy skomponować to narzędzie z innym, Omit
, aby uczynić opcjonalnymi tylko niektóre właściwości tego typu. W końcu utworzymy typ narzędzia za pomocą generyków TypeScript, aby zastosować to na dowolnym typie.
Ustaw wszystkie właściwości typu jako opcjonalne
Narzędzia Partial
i Omit
są dobrze znane w dziedzinie TypeScript, ponieważ są bardzo przydatne do szybkiego zastosowania ich do typu i uzyskania zasadniczo nowego typu. Partial<T>
przekonwertuje wszystkie klucze danego typu na opcjonalne. Jeśli na przykład masz ten typ:
interface Band {
lead: string
guitar: string
bass: string
drums: string
keyboard: string
}
wszystkie właściwości są wymagane, gdy coś ma ten typ. Jeśli chcesz przypisać taki obiekt:
const FooFighters: Band = {
lead: 'Dave Grohl',
guitar: 'Pat Smears',
bass: 'Nate Mendel',
drums: 'Taylor Williams',
}
nie powiedzie się, ponieważ brakuje keyboard
właściwości. Teraz moglibyśmy oznaczyć tę właściwość jako opcjonalną, a TypeScript łatwo nam to umożliwia. Najprostszym sposobem na to jest dodanie znaku zapytania do jego nazwy. W takim przypadku, jeśli istnieje możliwość edycji oryginalnego typu, możesz przejść do niego i zmodyfikować go w ten sposób:
interface Band {
lead: string
guitar: string
bass: string
drums: string
keyboard?: string
}
Świetny. Teraz poprzednie zadanie się powiedzie, ponieważ keyboard
nie jest już wymagane. Ale co, jeśli z jakiegokolwiek powodu nie można zmienić oryginalnego typu? To, co możesz szybko zrobić w takich przypadkach, to zastosować Partial
się do tego typu:
type NotAllTheBand = Partial
const FooFighters: NotAllTheBand = {
lead: 'Dave Grohl',
guitar: 'Pat Smears',
bass: 'Nate Mendel',
drums: 'Taylor Williams',
}
To przestaje wymuszać wszystkie właściwości, czyniąc je opcjonalnymi. Może czasami tego chcemy, ale co, jeśli chcemy, aby tylko jedna właściwość była opcjonalna i uniknąć modyfikowania oryginalnego typu?
Usuwanie właściwości z typu
Zanim przejdziemy do tego i zobaczymy, jak to działa, zobaczmy inne narzędzie, które nam w tym pomoże: Omit
. Ten typ narzędzia usuwa właściwości z typu, w którym jest stosowany. Chociaż Partial
nie przyjmuje innych argumentów niż typ, Omit
przyjmuje typ oraz właściwości, które chcesz usunąć: Omit<T, K>
.
To nie jest tak Partial
, że czyni je opcjonalnymi: Omit
całkowicie wymazuje je z typu. Kiedy używasz Partial<Band>
, to tak, jakbyś to zrobił:
interface Band {
lead?: string
guitar?: string
bass?: string
drums?: string
keyboard?: string
}
Jednak gdy używasz Omit<Band, 'keyboard'>
, to tak, jakbyś to zrobił:
interface Band {
lead: string
guitar: string
bass: string
drums: string
}
Teraz zaczyna to mieć sens, prawda? Czy możesz sobie wyobrazić, co moglibyśmy zrobić w TypeScript, jeśli mamy typ, który ma wszystkie właściwości oryginalnego zestawu jako opcjonalny, a inny typ ma tylko te właściwości, których chcemy wymagać? Gdyby tylko istniał sposób… przecinania się tych typów, prawda?
Przecinające się typy
Tak, w TypeScript można użyć znaku ampersand &
, operatora przecięcia typu. Ten operator, mając dwa typy, konstruuje nowy z właściwościami należącymi do obu typów:
interface SomeType {
propA: string
propB: number
}
interface AnotherType {
propC: boolean
propD: Array
}
type IntersectedType = SomeType & AnotherType
Do tej pory prawdopodobnie już się zorientowałeś: zamierzamy przeciąć typ częściowy i typ, w którym usunęliśmy niektóre jego właściwości.
Ustaw wybrane właściwości typu jako opcjonalne
Spróbujmy to zrozumieć. Podczas nauki języka TypeScript ważne jest, aby zracjonalizować to, co dzieje się z naszymi typami.
Zamierzamy pobrać typ, który ma wszystkie właściwości ustawione jako opcjonalne dzięki Partial
zastosowaniu na nim. Następnie przetniemy go z typem, który ma wybrane właściwości usunięte przez Omit
. Zobaczmy przykład:
interface SomeType {
propA: string
propB: number
}
type OptionalPropB = Partial & Omit
Mamy teraz nowy typ, bez modyfikowania oryginalnego typu, który wygląda następująco:
type OptionalPropB = {
propA: string
propB?: string
}
Dzieje się tak, ponieważ pobieramy właściwości propA?
z propB?
typu produkowanego przez Partial
i przecinamy je z propA
typem produkowanym przez Omit
.
Ogólne narzędzia TypeScript
Ok, teraz nasz nowy typ działa i możemy mieć tylko wybrane właściwości oznaczone jako opcjonalne bez modyfikowania oryginalnego typu. Jednak ta linia
type OptionalPropB = Partial & Omit
Jest zbyt gadatliwy, dość brzydki i nużący, by pisać za każdym razem. Co ważniejsze, nie zadziała dla innego typu, za każdym razem będziemy musieli napisać to od nowa. Czy możemy go skrócić i upiększyć i sprawić, by działał dla każdego typu? Tak, TypeScript pozwala nam tutaj użyć generyków i stworzyć własny typ narzędzia:
type Optional = Partial & Omit
A teraz mamy własny typ narzędzia TypeScript zaimplementowany z rodzajami, których możemy użyć, aby uczynić wybrane właściwości typu opcjonalnymi w dowolnym typie. Możemy go użyć tak:
type TypeWithOptionalProp = Optional
Zauważysz, że podpis jest podobny do Pomiń: to narzędzie przyjmuje typ, na którym ma działać, oraz właściwości, które będą opcjonalne. Jeśli masz więcej, możesz skorzystać z operatora union:
type TypeWithOptionalProps = Optional
Słowa zamykające
Możesz teraz zapisać ten ogólny typ narzędzia w pliku i wyeksportować go, aby używać go w całej aplikacji. Oto link do placu zabaw TypeScript, w którym dodałem kod z tego artykułu i skomentowałem go, dzięki czemu można zobaczyć, co się dzieje, patrząc na Partial
, Omit
i nasz ogólny typ narzędzia.
Świat generyków i narzędzi jest fantastyczny w TypeScript. Wejdź w to i zacznij eksperymentować!