Typescript delmängd av enum
I Typescript har jag en enum som
export enum CarBrands {
Toyota = "TOYOTA"
Ford = "FORD"
.....
}
Jag skulle vilja skapa en delmängd av denna enum på detta sätt men verkar inte kunna göra det
enum JapaneseCars {
CarBrands.Toyota
}
eller skapa ett objekt med en delmängd
const JapaneseCars = {
Carbrands.Toyota
}
Finns det något sätt jag kan skapa ett objekt eller enum som använder de värdena från ett annat befintligt enum?
Jag kan inte ändra CarBrands-enum till att vara en annan datatyp
Svar #1
Du kan skapa en type och const-kombination som kommer att fungera som ett enum som är en delmängd av ett annat enum.
Nackdel: denna lösning tvingar dig att ha varje enum-nyckel matcha sitt värde (eller så har jag inte hittat en lösning som hanterar det fallet än)
// Given an enum
export enum CarBrand {
TOYOTA = 'TOYOTA',
FORD = 'FORD',
PEUGEOT = 'PEUGEOT',
RENAULT = 'RENAULT'
}
// We can create the type of the subset
export type FrenchCarBrand = Extract<CarBrand, CarBrand.PEUGEOT | CarBrand.RENAULT>;
// And the const that goes with it
export const FrenchCarBrand = {
[CarBrand.PEUGEOT]: CarBrand.PEUGEOT,
[CarBrand.RENAULT]: CarBrand.RENAULT
} as const;
// With that you can :
// assign a CarBrand to a FrenchCarBrand ...
const a: FrenchCarBrand = CarBrand.RENAULT;
// ... as long as the CarBrand is in the type
const a_invalid: FrenchCarBrand = CarBrand.TOYOTA; // Type 'CarBrand.TOYOTA' is not assignable to type 'FrenchCarBrand'.
// assign a FrenchCarBrand to a CarBrand ...
const b: CarBrand = FrenchCarBrand.PEUGEOT;
// ... as long as the key exists
const b_invalid: CarBrand = FrenchCarBrand.TOYOTA; // Property 'TOYOTA' does not exist on type 'Readonly<Record<FrenchCarBrand, FrenchCarBrand>>'
// You cannot reassign the value of a FrenchCarBrand ...
FrenchCarBrand.PEUGEOT = CarBrand.RENAULT; // Cannot assign to 'PEUGEOT' because it is a read-only property.
// ... just like you cannot reassign the value of an enum
CarBrand.TOYOTA = 'MAZDA'; // Cannot assign to 'TOYOTA' because it is a read-only property.
Om du vill mappa ett okänt värde av typen CarBrand till ett värde av typen FrenchCarBrand, kommer det dock inte att fungera :
declare const brand: CarBrand;
const frenchBrand: FrenchCarBrand = brand; // Type 'CarBrand' is not assignable to type 'FrenchCarBrand'
// You can use the `as` keyword but it will hide bugs, so I do not recommend at all.
const frenchBrandNoError: FrenchCarBrand = brand as FrenchCarBrand; // No error, but a possible bug in your application.
För det behöver du en typvakt :
export const isFrenchCarBrand = (brand: CarBrand): brand is FrenchCarBrand => {
return brand in FrenchCarBrand;
}
Det kommer att låta dig bestämma vad du ska göra om du stöter på ett oönskat värde
if (isFrenchCarBrand(brand)) {
// You can safely assume that `brand` is a `FrenchCarBrand`
} else {
// `brand` is definitely not a `FrenchCarBrand`
}
Jag har gjort en TypeScript Playground som visar all denna kod med typkontroll i action
Svar #2
Jag tror att du letar efter något som detta -
export enum CarBrands {
Toyota = "TOYOTA",
Ford = "FORD"
}
type JapaneseCars = CarBrands.Toyota;
const car: JapaneseCars;
