Last active
January 31, 2022 02:51
-
-
Save disco0/245470b74db83daecc7ca78fc3697da6 to your computer and use it in GitHub Desktop.
TypeScript 4.1 - Template Literal Utility Types
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copied with additions from querySelector template literal types example | |
type Split<S extends string, D extends string> = S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] : [S]; | |
type SplitUnion<S extends string, D extends string> = Split<S, D>[number]; | |
type TakeLast<V> = V extends [] ? never : V extends [string] ? V[0] : V extends [string, ...infer R] ? TakeLast<R> : never; | |
type TrimLeft<V extends string> = V extends ` ${infer R}` ? TrimLeft<R> : V; | |
type TrimRight<V extends string> = V extends `${infer R} ` ? TrimRight<R> : V; | |
type Trim<V extends string> = TrimLeft<TrimRight<V>>; | |
type StripModifier<V extends string, M extends string> = V extends `${infer L}${M}${infer A}` ? L : V; | |
type StripModifiers<V extends string> = StripModifier<StripModifier<StripModifier<StripModifier<V, '.'>, '#'>, '['>, ':'>; | |
type TakeLastAfterToken<V extends string, T extends string> = StripModifiers<TakeLast<Split<Trim<V>, T>>>; | |
type GetLastElementName<V extends string> = TakeLastAfterToken<TakeLastAfterToken<V, ' '>, '>'>; | |
type GetEachElementName<V, L extends string[] = []> = | |
V extends [] ? L : | |
V extends [string] ? [...L, GetLastElementName<V[0]>] : | |
V extends [string, ...infer R] ? GetEachElementName<R, [...L, GetLastElementName<V[0]>]> : []; | |
type GetElementNames<V extends string> = GetEachElementName<Split<V, ','>>; | |
type ElementByName<V extends string> = | |
V extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[V] : | |
V extends keyof SVGElementTagNameMap ? SVGElementTagNameMap[V] : Element; | |
type MatchEachElement<V, L extends Element | null = null> = | |
V extends [] ? L : | |
V extends [string] ? L | ElementByName<V[0]> : | |
V extends [string, ...infer R] ? MatchEachElement<R, L | ElementByName<V[0]>> | |
: L; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment