Skip to content

Instantly share code, notes, and snippets.

@Akkuma
Last active March 20, 2024 13:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Akkuma/7ecc69a504e7a6fdd00e253737b61807 to your computer and use it in GitHub Desktop.
Save Akkuma/7ecc69a504e7a6fdd00e253737b61807 to your computer and use it in GitHub Desktop.
Tailwind Width Type Magic
/* Widths */
type TailwindFractionalWidth = `w-${number}/${number}`;
export type TailwindWidth =
| `w-${number}`
| TailwindFractionalWidth
| 'w-full'
| 'w-auto'
| `w-[clamp(${string},${string},${string})]`;
export type TailwindMinWidth = `min-${Exclude<TailwindWidth, TailwindFractionalWidth>}`;
export type TailwindMaxWidth =
| `max-${Exclude<TailwindWidth, TailwindFractionalWidth>}`
| `max-w-${TailwindBreakpoints}`
| `max-w-[${number}%]`;
export type TailwindBreakpoints = 'sm' | 'md' | 'lg' | 'xl' | '2xl';
export type TailwindMinBreakpoints = `min-${TailwindBreakpoints}`;
export type TailwindMaxBreakpoints = `max-${TailwindBreakpoints}`;
export type Width =
| TailwindWidth
| `${TailwindBreakpoints | TailwindMinBreakpoints | TailwindMaxBreakpoints}:${TailwindWidth}`;
export type MaxWidth =
| TailwindMaxWidth
| `${TailwindBreakpoints | TailwindMinBreakpoints | TailwindMaxBreakpoints}:${TailwindMaxWidth}`;
export type MinWidth =
| TailwindMinWidth
| `${TailwindBreakpoints | TailwindMinBreakpoints | TailwindMaxBreakpoints}:${TailwindMinWidth}`;
export type AnyWidth = Width | MaxWidth | MinWidth;
type IsWidth<T extends string> = T extends AnyWidth ? true : false;
type AreAllWidths<T extends string[], Pos extends number[] = []> = T extends [infer Head, ...infer Tail]
? Head extends string
? IsWidth<Head> extends true
? Tail extends string[]
? AreAllWidths<Tail, [0, ...Pos]>
: never
: Head extends ''
? never
: `${Head} is an invalid tailwind width class or unsupported at index ${Pos['length']}`
: never
: true;
export type Split<
S extends string,
Delimiter extends string,
Acc extends string[] = [],
> = S extends `${infer Head}${Delimiter}${infer Tail}`
? Split<Tail, Delimiter, [Head, ...Acc]>
: S extends Delimiter
? Acc
: [S, ...Acc];
type Reverse<T, Acc extends unknown[] = []> = T extends [infer Head, ...infer Tail]
? Reverse<Tail, [Head, ...Acc]>
: Acc;
type WidthsStr<T extends string, AAW = AreAllWidths<Reverse<Split<T, ' '>>>> = AAW extends never
? never
: AAW extends string
? { err: AAW }
: T;
export type Widths<T extends string, WS = WidthsStr<T>> = T extends ''
? AnyWidth
: WS extends { err: string }
? WS['err']
: WS extends T
? T
: never;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment