TypeScript: valda egenskaper valfria med Partial & Utelämna
När du använder verktyget Partial
på en typ kommer det att göra alla typegenskaper valfria. Låt oss se hur vi kan komponera det här verktyget med ett annat, Omit
, för att göra valfria endast vissa egenskaper av denna typ. Vi kommer äntligen att skapa en verktygstyp med Generics TypeScript för att tillämpa detta på vilken typ vi vill ha.
Gör alla egenskaper av en typ valfria
Verktygen Partial
och Omit
är välkända i TypeScript- sfären eftersom de är väldigt praktiska för att snabbt applicera dem på en typ och få vad som i princip är en ny typ. Partial<T>
konverterar alla nycklar av en typ till att vara valfria. Om du till exempel har den här typen:
interface Band {
lead: string
guitar: string
bass: string
drums: string
keyboard: string
}
alla egenskaper krävs när något har den här typen. Om du vill tilldela ett objekt så här:
const FooFighters: Band = {
lead: 'Dave Grohl',
guitar: 'Pat Smears',
bass: 'Nate Mendel',
drums: 'Taylor Williams',
}
det kommer att misslyckas eftersom det saknar keyboard
egendomen. Nu kan vi markera den här egenskapen som valfri och TypeScript låter oss enkelt göra det. Det mest grundläggande sättet att göra det är genom att sätta ett frågetecken till namnet. I det här fallet, om det är möjligt att redigera originaltypen, kan du gå till den och ändra den så här:
interface Band {
lead: string
guitar: string
bass: string
drums: string
keyboard?: string
}
Bra. Nu kommer det tidigare uppdraget att lyckas eftersom det keyboard
inte längre krävs. Men vad händer om det inte är möjligt att ändra originaltypen av någon anledning? Vad du snabbt kan göra i dessa fall är att ansöka Partial
om denna typ:
type NotAllTheBand = Partial
const FooFighters: NotAllTheBand = {
lead: 'Dave Grohl',
guitar: 'Pat Smears',
bass: 'Nate Mendel',
drums: 'Taylor Williams',
}
Detta slutar upprätthålla alla egenskaper, vilket gör dem alla valfria. Kanske vill vi ibland ha det här, men tänk om vi bara vill göra bara en egenskap valfri och undvika att modifiera den ursprungliga typen?
Ta bort egenskaper från en typ
Innan vi går vidare till det och ser hur det fungerar, låt oss se ett annat verktyg som hjälper oss med detta: Omit
. Den här verktygstypen tar bort egenskaper från typen där den har tillämpats. Medan Partial
tar inte andra argument än typen, Omit
tar typen plus de egenskaper du vill ta bort: Omit<T, K>
.
Det är inte så Partial
att det gör dem valfria: Omit
kommer att helt utplåna dem från typen. När du använder Partial<Band>
det är det som om du har gjort detta:
interface Band {
lead?: string
guitar?: string
bass?: string
drums?: string
keyboard?: string
}
Men när du använder Omit<Band, 'keyboard'>
, är det som om du har gjort det här:
interface Band {
lead: string
guitar: string
bass: string
drums: string
}
Det här börjar bli vettigt nu, eller hur? Kan du föreställa dig vad vi skulle kunna göra i TypeScript om vi har en typ som har alla egenskaper för den ursprungliga uppsättningen till valfri och en annan typ som bara har de egenskaper som vi vill kräva? Om det bara fanns ett sätt att… skära dessa typer, eller hur?
Korsande typer
Ja, det finns ett sätt i TypeScript att använda et-tecken &
, typskärningsoperatorn. Denna operatör, givet två typer, konstruerar en ny med egenskaperna som hör till båda typerna:
interface SomeType {
propA: string
propB: number
}
interface AnotherType {
propC: boolean
propD: Array
}
type IntersectedType = SomeType & AnotherType
Vid det här laget har du förmodligen räknat ut det: vi kommer att skära en partialiserad typ och en typ där vi tog bort några av dess egenskaper.
Gör valda egenskaper av en typ valfria
Låt oss försöka förstå det. Det är viktigt när man lär sig TypeScript att rationalisera vad som händer med våra typer.
Vi ska ta en typ som har alla dess egenskaper inställda på valfria tack vare Partial
applicerade på den. Därefter ska vi skära den med en typ som har valda egenskaper borttagna av Omit
. Låt oss se ett exempel:
interface SomeType {
propA: string
propB: number
}
type OptionalPropB = Partial & Omit
Vi har nu en ny typ, utan att ändra den ursprungliga typen, som ser ut som följande:
type OptionalPropB = {
propA: string
propB?: string
}
Detta händer eftersom vi tar tag i egenskaper propA?
och propB?
från typen som produceras av Partial
och korsar dem med propA
från typen som produceras av Omit
.
Generiska TypeScript-verktyg
Ok, nu fungerar vår nya typ och vi kan bara markera valda egenskaper som valfria utan att ändra den ursprungliga typen. Men denna linje
type OptionalPropB = Partial & Omit
Är för mångfacetterad, ganska ful och tråkig att skriva varje gång. Ännu viktigare, det kommer inte att fungera för en annan typ, vi måste skriva det igen varje gång. Kan vi göra det kortare och snyggare och få det att fungera för alla typer? Ja, TypeScript tillåter oss att använda generika här och skapa vår egen verktygstyp:
type Optional = Partial & Omit
Och nu har vi vår egen TypeScript-verktygstyp implementerad med generika som vi kan använda för att göra valda typegenskaper valfria i alla typer. Vi kan använda det så här:
type TypeWithOptionalProp = Optional
Du kommer att märka att signaturen liknar utelämna: det här verktyget tar typen att arbeta på och egenskaperna som kommer att göras valfria. Om du har fler kan du använda den fackliga operatören:
type TypeWithOptionalProps = Optional
Avslutningsord
Du kan nu spara den här generiska verktygstypen i en fil och exportera den för att använda den i hela appen. Här är en länk till en TypeScript-lekplats där jag la till koden från den här artikeln och kommenterade den så att du kan se vad som händer, titta på Partial
, Omit
, och vår generiska verktygstyp.
Världen av generika och verktyg är fantastisk i TypeScript. Kom in i det och börja experimentera!