interface UpperChars {
'A': 'a',
'B': 'b',
'C': 'c',
'D': 'd',
'E': 'e',
'F': 'f',
'G': 'g',
'H': 'h',
'I': 'i',
"J": 'j',
'K': 'k',
"L": 'l',
"M": 'm',
'N': 'n',
'O': 'o',
'P': 'p',
'Q': 'q',
'R': 'r',
'S': 's',
'T': 't',
'U': 'u',
'V': 'v',
'W': 'w',
'X': 'x',
'Y': 'y',
'Z': 'z'
}
type KebabCase<S extends string, ACC extends string = ''> = S extends '-' ? S
: S extends `${infer First extends keyof UpperChars}${infer Rest}`
? KebabCase<Rest, `${ACC}-${UpperChars[First]}`>
: S extends `${infer First}${infer Rest}`
? KebabCase<Rest, `${ACC}${First}`>
: ACC extends `-${infer Result}` ? Result : ACC
Solution by eunsukimme #35241
type KebabCase<
T extends string,
P extends string = ""
> = T extends `${infer L}${infer Rest}`
? Equal<Lowercase<L>, L> extends true
? `${L}${KebabCase<Rest, L>}`
: `${P extends "" ? P : "-"}${Lowercase<L>}${KebabCase<Rest, L>}`
: T;
Solution by wan-kong #35104
type KebabCase<
T extends string,
K extends string = "",
> = T extends `${infer L}${infer R}`
? L extends Lowercase<L>
? KebabCase<R, `${K}${L}`>
: KebabCase<R, `${K}${K extends "" ? "" : "-"}${Lowercase<L>}`>
: K;
Solution by Artawower #34840
type KebabCase<S extends string> = S extends `${infer First}${infer Rest}`? Rest extends Uncapitalize<Rest> ? `${Uncapitalize<First>}${KebabCase<Rest>}` : `${Uncapitalize<First>}-${KebabCase<Rest>}` : S
Solution by devshinthant #34611
type KebabCase<
S extends string,
Previous extends string = ""
> = S extends `${infer First}${infer Rest}`
? Lowercase<First> extends First
? `${First}${KebabCase<Rest, First>}`
: Previous extends ""
? `${Lowercase<First>}${KebabCase<Rest, First>}`
: `-${Lowercase<First>}${KebabCase<Rest, First>}`
: "";
Solution by yukicountry #34389
使用工具类型 Uncapitalize:
Uncapitalize
type KebabCase<T extends string> =
T extends `${infer A}${infer B}`?
B extends Uncapitalize<B>? `${Uncapitalize<A>}${KebabCase<B>}` : `${Uncapitalize<A>}-${KebabCase<B>}`
:T
Solution by Jayce-liang #34283
type KebabCase<S extends string> = S extends `${infer R}${infer rest}` ? (rest extends Uncapitalize<rest> ? `${Uncapitalize<R>}${KebabCase<Uncapitalize<rest>>}` : `${Uncapitalize<R>}-${KebabCase<Uncapitalize<rest>>}`) : S
Solution by ouzexi #34021
type KebabCase<S extends string> = S extends `${infer S1}${infer S2}${infer S3}`
? S2 extends Lowercase<S2>
? `${Lowercase<S1>}${KebabCase<`${S2}${S3}`>}`
: `${Lowercase<S1>}-${KebabCase<`${Lowercase<S2>}${S3}`>}`
: S
Solution by waysjd #34003
by Johnson Chu (@johnsoncodehk) #medium #template-literal
Replace the camelCase
or PascalCase
string with kebab-case
.
FooBarBaz
-> foo-bar-baz
For example
type FooBarBaz = KebabCase<"FooBarBaz">
const foobarbaz: FooBarBaz = "foo-bar-baz"
type DoNothing = KebabCase<"do-nothing">
const doNothing: DoNothing = "do-nothing"
View on GitHub: https://tsch.js.org/612
...
type KebabCase<S extends string, F = S[0]> = S extends `${infer L}${infer R}`
? R extends Uncapitalize<R>
? `${Uncapitalize<L>}${KebabCase<R>}`
: `${Uncapitalize<L>}-${KebabCase<R>}`
: S
Solution by veralex #33802
解决两个问题:
1. 如何判断是否为大写字母
T extends Uppercase<T> 为true 同时 T extends Lowercase<T> 为false,则该字母为大写字母
2. 是否为首字母
默认为true,其他传值为false
// 判断是否为大写字母
type isUpperLetter<T extends string> = T extends Uppercase<T>
? T extends Lowercase<T>
? false
: true
: false;
type KebabCase<S, IsFirst = true> = S extends `${infer L}${infer R}`
? `${isUpperLetter<L> extends true ? IsFirst extends true ? '' : '-' : ''}${Lowercase<L>}${KebabCase<R, false>}`
: S;
Solution by chenghao125 #33432
// 判断是否为大写字母
type isUpperLetter<T extends string> = T extends Uppercase<T>
? T extends Lowercase<T>
? false
: true
: false;
type KebabCase<S, IsFirst = true> = S extends `${infer L}${infer R}`
? `${isUpperLetter<L> extends true ? IsFirst extends true ? '' : '-' : ''}${Lowercase<L>}${KebabCase<R, false>}`
: S;
Solution by chenghao125 #33431
// your answers
type KebabCase<S> = S extends `${infer R}${infer T}`
? `${Uncapitalize<R>}${T extends Uncapitalize<T> ? "" : "-"}${KebabCase<T>}`
: S
The KebabCase type recursively breaks down a string into its first character and the rest, converting the first character to lowercase and adding a hyphen before any uppercase letters in the rest of the string. This process continues until the entire string is transformed into kebab-case
Solution by lezhu1234 #33284
interface Hi{ 'A':'a'; 'B':'b'; 'F':'f'; }
type KebabCaseMy<T extends string, D extends string =''>
= D extends ''
? T extends ${infer C extends keyof Hi}${infer R}
? KebabCaseMy<R,${D}${Hi[C]}
>
: T extends ${infer C}${infer R}
? KebabCaseMy<R,${D}${C}
>
:D
:T extends ${infer C extends keyof Hi}${infer R}
? KebabCaseMy<R,${D}-${Hi[C]}
>
: T extends ${infer C}${infer R}
? KebabCaseMy<R,${D}${C}
>
: D;
Solution by Shlufman #33083
type UnCapitalize<S extends string> = S extends `${infer F}${infer R}`
? `${Lowercase<F>}${R}`
: ''
type KebabCase<S extends string, Acc extends string = ''> = S extends `${infer F}${infer R}`
? R extends UnCapitalize<R>
? KebabCase<R, `${Acc}${F}`>
: `${UnCapitalize<`${Acc}${F}`>}-${KebabCase<R>}`
: UnCapitalize<Acc>
Solution by rimo030 #32980
type UpperMap = {
'A': 'a'
'B': 'b'
'C': 'c'
'D': 'd'
'E': 'e'
'F': 'f'
'G': 'g'
'H': 'h'
'I': 'i'
'J': 'j'
'K': 'k'
'L': 'l'
'M': 'm'
'N': 'n'
'O': 'o'
'P': 'p'
'Q': 'q'
'R': 'r'
'S': 's'
'T': 't'
'U': 'u'
'V': 'v'
'W': 'w'
'X': 'x'
'Y': 'y'
'Z': 'z'
}
type Upper = keyof UpperMap
type Step1<S extends string> = S extends `${infer Cap}${infer Rest}` ? Cap extends Upper ? `${UpperMap[Cap]}${Rest}` : S : S
type Step2<S extends string, A extends string = ''> = S extends `${infer Cap}${infer Rest}` ? Cap extends Upper ? Step2<Rest, `${A}-${UpperMap[Cap]}`> : Step2<Rest, `${A}${Cap}`> : A
type KebabCase<S extends string> = Step2<Step1<S>>
Solution by ZJia1231 #32489
type KebabCase<S extends string> =
S extends `${infer First}${infer Rest}`
? Rest extends Uncapitalize<Rest>
? `${Uncapitalize<First>}${KebabCase<Rest>}`
: `${Uncapitalize<First>}-${KebabCase<Rest>}`
: S
재귀적 사고, Uncapitalize 유틸리티 타입
Solution by dev-hobin #32417
// your answers
type KebabCase<S extends string> = S extends `${infer L}${infer R}`
? R extends Uncapitalize<R>
? `${Uncapitalize<L>}${KebabCase<R>}`
: `${Uncapitalize<L>}-${KebabCase<R>}`
: S;
Solution by pea-sys #32355
type KebabCase<S extends string, U extends string = S> = U extends `${infer F}${infer L}`
? L extends ""
? F extends ToUpperCase
? S extends `${infer F1}${F}`
? F1 extends ""
? `${LowerCase[F]}`
: `${F1}-${LowerCase[F]}`
: never
: S
: F extends ToUpperCase
? KebabCase<
S extends `${infer F2}${F}${infer L1}`
? F2 extends ""
? `${LowerCase[F]}${L1}`
: `${F2}-${LowerCase[F]}${L1}`
: S,
L
>
: KebabCase<S, L>
: "";
interface LowerCase {
A: "a";
B: "b";
C: "c";
D: "d";
E: "e";
F: "f";
G: "g";
H: "h";
I: "i";
J: "j";
K: "k";
L: "l";
M: "m";
N: "n";
O: "o";
P: "p";
Q: "q";
R: "r";
S: "s";
T: "t";
U: "u";
V: "v";
W: "w";
X: "x";
Y: "y";
Z: "z";
}
type ToUpperCase = keyof LowerCase;
Solution by gasmg #32002
type KebabCase<S> = S extends `${infer S1}${infer S2}`
? S2 extends Uncapitalize<S2>
? `${Uncapitalize<S1>}${KebabCase<S2>}`
: `${Uncapitalize<S1>}-${KebabCase<S2>}`
: S;
Solution by jinyoung234 #31937
type KebabCase<S> = S extends `${infer S1}${infer S2}`
? S2 extends Uncapitalize<S2> ? `${Uncapitalize<S1>}${KebabCase<Uncapitalize<S2>>}` : `${Uncapitalize<S1>}-${KebabCase<Uncapitalize<S2>>}`
: S;
Solution by kai-phan #31657
type KebabCase<S extends string> = S extends `${infer S1}${infer S2}`
? S2 extends Uncapitalize<S2>
? `${Uncapitalize<S1>}${KebabCase<S2>}`
: `${Uncapitalize<S1>}-${KebabCase<S2>}`
: S;
Solution by vipulpathak113 #31515
type KebabCase<S extends string> = S extends `${infer S1}${infer S2}`
? S2 extends Uncapitalize<S2>
? `${Uncapitalize<S1>}${KebabCase<S2>}`
: `${Uncapitalize<S1>}-${KebabCase<S2>}`
: S;
Solution by MyeonghoonNam #31440
type KebabCase<S extends string, P extends string = ''> =
S extends `${infer A}${infer Rest}`
? Lowercase<A> extends Uppercase<A>
? `${A}${KebabCase<Rest, '-'>}`
: `${A extends Uppercase<A> ? `${P}${Lowercase<A>}` : A}${KebabCase<Rest, '-'>}`
: S;
Solution by ricky-fn #31337
type Uppers = {
F:'f',
B:'b',
C:'c',
A:'a',
//...
}
type KebabCase<S extends string, Tmp extends string = ""> = S extends `${infer A}${infer B}` ? KebabCase<B, `${Tmp}${A extends keyof Uppers ? `${Tmp extends '' ? '':'-'}${Uppers[A]}` : A}`> : Tmp;
Solution by eward957 #31251
// your answers
type KebabCase<S> = S extends `${infer First}${infer Rest}`
? Rest extends Uncapitalize<Rest>
? `${Lowercase<First>}${KebabCase<Rest>}`
: `${Lowercase<First>}-${KebabCase<Rest>}`
: S;
Solution by d1zzzzy #31230
// your answers
type KebabCase<S extends string, Pre extends string = ''> = S extends `${infer L}${infer Rest}` ? (
L extends Lowercase<L> ? KebabCase<Rest, `${Pre}${L}`> : (
(Pre extends '' ? KebabCase<Rest, `${Lowercase<L>}`>
: KebabCase<Rest, `${Pre}-${Lowercase<L>}`>)
)
): Pre;
Solution by CDSP98 #31031
type KebabCase<S, P = S> = S extends `${infer C}${infer R}`
? IsUppercase<C> extends true
? `${C}${R}` extends `${infer ST}` // is uppercase letters
? `${ST extends P /* is first letters */ ? '' : '-'}${Lowercase<C>}${KebabCase<R, P>}`
: never
: `${C}${KebabCase<R, P>}`
: S // single letters
type IsUppercase<T extends string> = T extends Uppercase<T>
? T extends Lowercase<T>
? false
: true
: false
Solution by Chan-Yuxi #30558
type KebabCase<S extends string, R extends string = ''> = S extends ''
? R
: S extends `${infer F}${infer Rest}`
? KebabCase<Rest, `${R}${F extends Uppercase<F> ? (Lowercase<F> extends F ? '' : R extends '' ? '' : '-') : ''}${Lowercase<F>}`>
: R;
Solution by kai-phan #30378
type KebabCase<S extends string> =
S extends `${infer L}${infer R}`
? R extends '' | `${Lowercase<string>}${string}`
? `${Lowercase<L>}${KebabCase<R>}`
: `${Lowercase<L>}-${KebabCase<R>}`
: ''
or
type KebabCase<S extends string> =
S extends `${infer L}${infer R}`
? R extends Uncapitalize<R>
? `${Uncapitalize<L>}${KebabCase<R>}`
: `${Uncapitalize<L>}-${KebabCase<R>}`
: ''
Solution by sbr61 #29972
type KebabCase<S extends string, T = Uncapitalize<S>> = T extends `${infer R}${infer P}`
? P extends Uncapitalize<P>
? `${R}${KebabCase<P>}`
: `${R}-${KebabCase<P>}`
: T
Solution by lovezhangchuangxin #29962