Last active
May 3, 2021 04:31
-
-
Save CurtisFenner/cbdc20a61a0fbfaa2aa095b9c4def737 to your computer and use it in GitHub Desktop.
This file contains 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
// Splits `T` at the first occurrence of `S`. | |
type SplitBy<T extends string, S extends string> = | |
T extends `${infer A}${S}${infer B}` | |
? { before: A, split: S, after: B } | |
: never; | |
type SplitInfo = { before: string, split: string, after: string }; | |
type UseShorter<A extends SplitInfo, B extends SplitInfo> = | |
A["before"] extends `${B["before"]}${infer R}` ? B : A; | |
// Given a tuple of `SplitInfo`, returns the one which has a `before` that is a | |
// prefix of all others. | |
type UseShortest<A extends SplitInfo[]> = | |
A extends [infer Only] | |
? Only & SplitInfo | |
: A extends [infer First, ...infer Rest] | |
? UseShorter<First & SplitInfo, UseShortest<Rest extends SplitInfo[] ? Rest : never>> | |
: never; | |
// Performs `SplitBy` on each splitter in `R`, and returns the shortest `before` | |
// split using `UseShortest`. | |
type ShortestSplit<T extends string, R extends [... string[]]> = UseShortest<{ [K in keyof R]: SplitBy<T, R[K] extends string ? R[K] : never> }>; | |
// Leaves `before` alone. | |
// Wraps each `split` in parentheses. | |
// Recursively invokes `Escaping` on the `after`. | |
type ExpandEscaping<T extends SplitInfo, Splitters extends [...string[]]> = | |
`${T["before"]}(${T["split"]})${Escaping<T["after"], Splitters>}`; | |
// Wrap each occurrence of any of the `Splitters` within `T` in parentheses. | |
type Escaping<T extends string, Splitters extends [...string[]]> = | |
T extends `${infer _1}${Splitters[number]}${infer _2}` | |
? ExpandEscaping<ShortestSplit<T, Splitters>, Splitters> | |
: T; | |
// type z = "alpha(,)beta(@)gamma(,)delta(@)banana" | |
type z = Escaping<"alpha,beta@gamma,delta@banana", [",", "@"]>; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment