String ersetzen beim Erstellen eines String-Literal-Union-Typs in TypeScript
Ich habe einen Unionstyp aus Zeichenkettenliteralen, der folgendermaßen aussieht:
type LowerCaseNames = 'youku-frame' | 'youku' | 'mini-program' | 'tiktok-frame';
Dies ist nur ein Beispiel, da mein Vereinigungstyp eine Liste von mehr als 100 Fällen ist.
Was ich brauche, ist ein neuer Typ, bei dem ich die folgenden "Werte" im Typ hätte:
type UpperCaseNames = 'YOUKU_FRAME' | 'YOUKU' | 'MINI_PROGRAM' | 'TIKTOK_FRAME';
Bisher verwende ich den Uppercase-Typ von TypeScript, um ihn in Großbuchstaben zu haben.
type UpperCaseNames = `${Uppercase<LowerCaseNames>}`;
Was dies zurückgibt, ist ein großgeschriebener Union-Typ, aber ich habe darin immer noch - statt _. Gibt es eine Möglichkeit, einen Typ zu erstellen, den ich so verwenden kann $ {Replace<Uppercase<LowerCaseNames>>}, um - durch _ zu ersetzen? Ich verwende Typescript v4.4.4.
Antwort #1
Sie können einen benutzerdefinierten Replace<T, S, D>-Utility-Typ schreiben, der einen String-Literaltyp T nimmt und eine neue Version erzeugt, bei der Vorkommen eines Quell-Strings S durch einen Ziel-String D ersetzt werden. Hier ist eine Möglichkeit, dies zu tun:
type Replace<T extends string, S extends string, D extends string,
A extends string = ""> = T extends `${infer L}${S}${infer R}` ?
Replace<R, S, D, `${A}${L}${D}`> : `${A}${T}`
Das ist ein tail-rekursiver Template-Literal-Typ, der einen Typ-Parameter A verwendet, um das Ergebnis zu akkumulieren. Wenn T die Form L+S+R für einen (möglicherweise leeren) „linken Teil“ L und einen (möglicherweise leeren) „rechten Teil“ R hat, dann möchten Sie L unverändert verwenden, S durch D ersetzen und dann weiterhin Replace-Operationen auf R durchführen. Andernfalls enthält T S nicht und Sie möchten T unverändert verwenden.
Lass es uns ausprobieren:
type LowerCaseNames = 'youku-frame' | 'youku' | 'mini-program' | 'tiktok-frame';
type UpperCaseNames = Uppercase<Replace<LowerCaseNames, "-", "_">>
// type UpperCaseNames = "YOUKU" | "YOUKU_FRAME" | "MINI_PROGRAM" | "TIKTOK_FRAME"
Sieht gut aus!
Playground-Link zum Code
