一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情。
题目二十七:camelcase
// template.ts
type CamelCase<S> = any;
// test-cases.ts
import { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<CamelCase<'foo-bar-baz'>, 'fooBarBaz'>>,
Expect<Equal<CamelCase<'foo-Bar-Baz'>, 'foo-Bar-Baz'>>,
Expect<Equal<CamelCase<'foo-Bar-baz'>, 'foo-BarBaz'>>,
Expect<Equal<CamelCase<'foo-bar'>, 'fooBar'>>,
Expect<Equal<CamelCase<'foo_bar'>, 'foo_bar'>>,
Expect<Equal<CamelCase<'foo--bar----baz'>, 'foo-Bar---Baz'>>,
Expect<Equal<CamelCase<'a-b-c'>, 'aBC'>>,
Expect<Equal<CamelCase<'a-b-c-'>, 'aBC-'>>,
Expect<Equal<CamelCase<'ABC'>, 'ABC'>>,
Expect<Equal<CamelCase<'-'>, '-'>>,
Expect<Equal<CamelCase<''>, ''>>,
Expect<Equal<CamelCase<'😎'>, '😎'>>,
]
将烤串转驼峰
测试用例
Equal<CamelCase<'foo-bar-baz'>, 'fooBarBaz'>
正常的将烤串语法转为驼峰语法
Equal<CamelCase<'foo-Bar-Baz'>, 'foo-Bar-Baz'>
如果相应需要转换的字母已经是大写了,则不进行转换
Equal<CamelCase<'foo_bar'>, 'foo_bar'>
只会对中划线进行转换
Equal<CamelCase<'foo--bar----baz'>, 'foo-Bar---Baz'>
多个中划线,只会删除一个后将其后方最近的一个字母转为大写
Equal<CamelCase<'a-b-c-'>, 'aBC-'>
如果中划线后方没有字母了,则不会对其进行操作
代码实现
在进行功能实现之前,我们先来认识一个TS函数:Capitalize(将首字母转大写)
/**
* Convert first character of string literal type to uppercase
*/
type Capitalize<S extends string> = intrinsic;
- 原代码
type CamelCase<S> = any;
- 传入的
S是一个字符串
type CamelCase<S extends string> = any;
- 将其根据中划线(
-)进行拆分,如果能拆出来则进行下一步操作,拆不出来则直接返回S
type CamelCase<S extends string> = S extends `${infer F}-${infer R}`
? ...
: S
- 判断拆分处理的右侧字符串,首字母是否是大写。
- 如果是大写,则不删除中划线直接对右侧字符串递归调用CamelCase
- 如果不是大写,则删除中划线,并将右侧首字母改为大写后,再递归
CamelCase
type CamelCase<S extends string> = S extends `${infer F}-${infer R}`
? R extends Capitalize<R>
? `${F}-${CamelCase<R>}`
: `${F}${CamelCase<Capitalize<R>>}`
: S
题目二十八:kebabcase
// template.ts
type KebabCase<S> = any
// test-cases.ts
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<KebabCase<'FooBarBaz'>, 'foo-bar-baz'>>,
Expect<Equal<KebabCase<'fooBarBaz'>, 'foo-bar-baz'>>,
Expect<Equal<KebabCase<'foo-bar'>, 'foo-bar'>>,
Expect<Equal<KebabCase<'foo_bar'>, 'foo_bar'>>,
Expect<Equal<KebabCase<'Foo-Bar'>, 'foo--bar'>>,
Expect<Equal<KebabCase<'ABC'>, 'a-b-c'>>,
Expect<Equal<KebabCase<'-'>, '-'>>,
Expect<Equal<KebabCase<''>, ''>>,
Expect<Equal<KebabCase<'😎'>, '😎'>>,
]
测试用例
Equal<KebabCase<'FooBarBaz'>, 'foo-bar-baz'>
如果是首字母大写,则直接转换成小写
如果是非首字母大写,则将其转换成小写后,前方添加中划线(-)
Equal<KebabCase<'foo_bar'>, 'foo_bar'>
只对中划线做处理
首字母小写的TS函数
/**
* Convert first character of string literal type to lowercase
*/
type Uncapitalize<S extends string> = intrinsic;
代码实现
- 原代码
type KebabCase<S> = any
- 入参
S是一个字符串
type KebabCase<S extends string> = any
- 将
S拆分为左右两个字符串(左边可以当作是首字母,右边是剩余部分)- 如果拆分出来了,则进行下一步
- 否则直接返回
S
type KebabCase<S extends string> = S extends `${infer L}${infer R}`
? ...
: S
- 首字母(
L)不论如何,都要转成小写。在此基础上,判断R是否是首字母小写的
type KebabCase<S extends string> = S extends `${infer L}${infer R}`
? R extends Uncapitalize<R>
? `${Uncapitalize<L>}...`
: `${Uncapitalize<L>}...`
: S
- 如果
R是首字母小写的,则不做任何处理,接着对其递归KebabCase - 否则添加中划线,再进行递归(不需要特意加上
Uncapitalize函数,因为KebabCase本身就含有首字母小写的功能了)
type KebabCase<S extends string> = S extends `${infer L}${infer R}`
? R extends Uncapitalize<R>
? `${Uncapitalize<L>}${KebabCase<R>}`
: `${Uncapitalize<L>}-${KebabCase<R>}`
: S