Skip to content

typescript template literal

Yongku cho edited this page Jul 12, 2023 · 5 revisions

Tailwind ClassName fill-* 대신 text- 사용하도록 처리

T extends `${infer U}fill${infer V}` ? `${U}text${V}` : T

Pair ClassName

w-*와 h-*가 항상 같은 사이즈를 사용해야 할 때 사용한 타입이다.

type SizeClass<
  U extends string,
  V extends string,
  Size extends string,
  Left extends string,
  Right extends string,
> = `${U}${Left}${Size} ${Right}${Size}${V}`;

type CheckPair<
  T,
  U extends string,
  V extends string,
  Size extends string,
  Left extends string,
  Right extends string,
> = T extends `${infer U}${Left}${Size} ${Right}${Size}${infer V}`
  ? SizeClass<U, V, Size, Left, Right>
  : SizeClass<U, ` ${V}`, Size, Left, Right>;

export type RequirePair<
  T,
  Left extends string,
  Right extends string,
> = T extends `${infer U}${Left}${infer Size} ${infer V}`
  ? CheckPair<T, U, V, Size, Left, Right>
  : T extends `${infer U}${Right}${infer Size} ${infer V}`
  ? CheckPair<T, U, V, Size, Left, Right>
  : T extends `${infer U}${Left}${infer Size}`
  ? SizeClass<U, "", Size, Left, Right>
  : T extends `${infer U}${Right}${infer Size}`
  ? SizeClass<U, "", Size, Left, Right>
  : T;

Tailwind ClassName Prefix Filter

type FilterString<
  S extends string,
  Target extends string,
> = S extends `${Target}${string | ""}` ? "" : S;

type Split<
  S extends string,
  D extends string,
  Prefix extends string,
> = S extends ""
  ? []
  : S extends `${infer T}${D}${infer U}`
  ? [`${FilterString<T, Prefix>}`, ...Split<U, D, Prefix>]
  : [`${FilterString<S, Prefix>}`];

type Join<S extends string[], D extends string> = S extends [
  infer Head,
  ...infer Tail,
]
  ? `${Head extends string ? Head : ""}${Head extends "" ? "" : D}${Join<
      Tail extends string[] ? Tail : [],
      D
    >}`
  : "";

type TrimRight<T extends string> = T extends `${infer R} `
  ? `${TrimRight<R>}`
  : T;

export type DisallowClassName<
  S extends string,
  Prefix extends string,
> = TrimRight<Join<Split<S, " ", Prefix>, " ">>;

// h-10 w-10 m-10 p-10
type FilteredClassName0 = DisallowClassName<
  "h-10 w-10 m-10 p-10 fill-black",
  "fill"
>;
type FilteredClassName1 = DisallowClassName<
  "h-10 w-10 fill-black m-10 p-10",
  "fill"
>;
type FilteredClassName2 = DisallowClassName<
  "fill-black h-10 w-10 m-10 p-10",
  "fill"
>;

// fill-black m-10 p-10
type FilteredClassName3 = DisallowClassName<
  "fill-black h-10 w-10 m-10 p-10",
  "h" | "w"
>;
Clone this wiki locally