Typescript: typ zjednotených literálov reťazcov z výčtu
Chcel by som získať zjednotenie reťazcových literálov z výčtu.
Pre tento výpočetný typ…
enum Weekday {
MONDAY = 'mon',
TUESDAY = 'tue',
WEDNESDAY = 'wed'
}
… Chcel by som dostať toto:
type WeekdayType = 'mon' | 'tue' | 'wed';
Skúšal som typeof keyof Weekday, ale to viedlo k 'MONDAY' | 'TUESDAY' | 'WEDNESDAY'. Mám pocit, že riešenie by mohlo súvisieť s mapovanými typmi, ale nedarí sa mi to pochopiť.
Ako to urobím?
Odpoveď č. 1
Pozri TS4.1 ODPOVEĎ:
type WeekdayType = `${Weekday}`;
PRE TS-4.1 ODPOVEĎ:
Toto sa nedá urobiť programovo... pokúšate sa previesť typ Weekday, čo je Weekday.MONDAY | Weekday.TUESDAY | Weekday.WEDNESDAY, na typ WeekdayType, čo je "mon" | "tue" | "wed". Táto konverzia je forma rozširovania, pretože Weekday je podtypom WeekdayType:
type WeekdayExtendsWeekdayType =
Weekday extends WeekdayType ? true : false
// type WeekdayExtendsWeekdayType = true
Bohužiaľ, kompilátor vám nedá meno na odstránenie "enum" z enum typu a zostanú vám len doslovné typy.
Takže, nejaké obchádzky? Možno vlastne nepotrebujete enum, ale môžete si vystačiť s objektom, ktorého vlastnosti sú literály reťazcov:
const lit = <V extends keyof any>(v: V) => v;
const Weekday = {
MONDAY: lit("mon"),
TUESDAY: lit("tue"),
WEDNESDAY: lit("wed")
}
type Weekday = (typeof Weekday)[keyof typeof Weekday],
Ak ho preskúmate, hodnota s názvom Weekday sa správa ako enum objekt:
console.log(Weekday.TUESDAY); // tue
zatiaľ čo typ s názvom Weekday sa správa ako zjednotenie reťazcových hodnôt "mon" | "tue" | "wed", ktoré ste volali WeekdayType:
const w: Weekday = "wed"; // okay
const x: Weekday = "xed"; // error
Takže pri tomto riešení neexistuje žiadna "enum" povaha, a preto nie je potrebné rozlišovať typ Weekday od typu WeekdayType. Je to trochu odlišné od skutočného enum (ktorý zahŕňa typy ako Weekday.MONDAY, ktorý by ste museli reprezentovať ako zdĺhavý typeof Weekday.MONDAY alebo vytvoriť preň iný alias typu), ale môže sa správať dosť podobne na to, aby to bolo užitočné. Funguje to pre vás?
Odpoveď č. 2
TypeScript 4.1+:
Ako bolo spomenuté, toto je možné dosiahnuť použitím typov šablónových literálov nasledovne:
type WeekdayType = `${Weekday}`;
TypeScript 3.4 a novšie:
Nadväzujúc na @jcalz odpoveď a komentár od @just-borisa, tu je príklad s tvrdeniami o const:
const Weekday = {
MONDAY: "mon",
TUESDAY: "tue",
WEDNESDAY: "wed",
} as const;
type Weekday = (typeof Weekday)[keyof typeof Weekday];
Odpoveď č. 3
S Typescriptom 4.1 sa to dá urobiť!
enum Weekday {
MONDAY = 'mon',
TUESDAY = 'tue',
WEDNESDAY = 'wed'
}
type WeekdayType = `${Weekday}`;
A pre číselné enumy, vďaka @okku:
enum ThreeDigits {
ZERO = 0,
ONE = 1,
TWO = 2
}
type ThreeDigitsType = `${ThreeDigits}` extends `${infer T extends number}` ? T : never;
