Skip to content

Instantly share code, notes, and snippets.

@disco0
Last active January 31, 2022 02:51
Show Gist options
  • Save disco0/245470b74db83daecc7ca78fc3697da6 to your computer and use it in GitHub Desktop.
Save disco0/245470b74db83daecc7ca78fc3697da6 to your computer and use it in GitHub Desktop.
TypeScript 4.1 - Template Literal Utility Types
// 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