Day16 模版字符串类型Template String Types
与js中的模版字符串语法一致${},ts中通过该语法也能实现字符串类型的拼接。
type World = 'World'
type Hello = `Hello ${World}`
type HelloType = `Hello ${string}`
const x : HelloType = 'Hello ';
const y : HelloType = 'Hello a'
type Version = `${number},${number},${number}`
const v1:Version = '1,2,3'
// error Type '"1,2"' is not assignable to type '`${number},${number},${number}`
const v2:Version = '1,2'
// 也可以通过范型传入 不过只支持下面的六种类型,其他类型无效
type Greet<T extends string | number | boolean | null | undefined | bigint>
= `Hello ${T}`;
// 比如传入symbol类型会报错
// Type 'symbol' is not assignable to type 'string | number | bigint | boolean | null | undefined'.(2322)
type greet = `${symbol('1')}`
// 模版语法中可以传入联合类型,最终的声明会自动进行类型组合
type Brand = 'iphone' | 'xiaomi';
type Memory = '16G';
type ItemType = 'official' | 'second-hand';
// type SKU = "iphone-16G-official" | "iphone-16G-second-hand" | "xiaomi-16G-official" | "xiaomi-16G-second-hand"
type SKU = `${Brand}-${Memory}-${ItemType}`;
重映射
配合模版字符串类型,ts支持了重映射语法,可以在映射键名时基于原键名做修改
// 使用as将key值映射到了模版语法内
// 使用 string & K 确保传入的类型为string,排除symbol
type Copy<T extends object> = {
[K in keyof T as `modified${string & K}`]:T[K];
}
interface Foo{
name: string;
age: number;
}
// type CopyFoo = {
// modifiedname: string;
// modifiedage: number;
// }
type CopyFoo = Copy<Foo>
// 专用字符串处理工具 Uppercase、Lowercase、Capitalize、Uncapitalize
// 首字母大写,实现小写驼峰
type Copy<T extends object> = {
[K in keyof T as `modified${Capitalize<string & K>}`]:T[K];
}
// type CopyFoo = {
// modifiedName: string;
// modifiedAge: number;
// }
type CopyFoo = Copy<Foo>
模式匹配
// 通过infer提取某一部分
type ReverseName<Str extends string> =
Str extends `${infer First} ${infer Last}`
? `${Capitalize<Last>} ${First}` : Str;
// "Hardy Tom"
type TomHardy = ReverseName<'Tom hardy'>;
Day17 模版字符串工具类型进阶
模版字符串类型和模式匹配结合,实现字符串处理类型
实现trim、includes
// trim 先去除left的空字符串,再去除right的空字符串
type TrimLeft<T extends string> = T extends ` ${infer End}` ? TrimLeft<End> : T;
type TrimRight<T extends string> = T extends `${infer Start} ` ? TrimRight<Start> : T;
type Trim<T extends string> = TrimLeft<TrimRight<T>>;
// include
type Include<Str extends string, Search extends string> =
Str extends `${infer Start}${Search}${infer End}` ? true : false;
type IncludeR1 = Include<'abc','a'> // true
type IncludeR2 = Include<'abc','ab'> // true
type IncludeR3 = Include<'abc',''> // true
type IncludeR4 = Include<' ',''> // true
// 处理传入空字符串的情况
type Include2<Str extends string, Search extends string> =
Str extends '' ? Search extends '' ? true : false : Include<Str,Search>;
type IncludeR5 = Include2<'',''> // true
实现replace、split和join
// replace replaceAll
type Replace<Str extends string,Search extends string, ReplaceMent extends string > =
Str extends `${infer Start}${Search}${infer End}`
? `${Start}${ReplaceMent}${End}` : Str;
type ReplaceR1 = Replace<'abcd','a','1'> // "1bcd"
// 需要注意,此实现,如果replacement传入包含了search字段,会死循环,可以有优化的空间?
type ReplaceAll<Str extends string,Search extends string, ReplaceMent extends string> =
Str extends `${infer Start}${Search}${infer End}`
? ReplaceAll<`${Start}${ReplaceMent}${End}`,Search,ReplaceMent> : Str;
type replaceAll = ReplaceAll<'www.baidu.com','w',''> // ".baidu.com"
// split
type Split<Str extends string,Delimiter extends string> =
Str extends `${infer Start}${Delimiter}${infer End}`
? [Start, ...Split<End,Delimiter>] : Str extends Delimiter ? [] : [Str];
type split = Split<'a-b-c','-'> // ["a", "b", "c"]
// 可以对split后的元祖类型使用length
type SplitLength = Split<'a-b-c','-'>['length'] // 3
// join
type Join<List extends Array<string | number>, Delimiter extends string> =
List extends []
? '' : List extends [string | number]
? `${List[0]}` : List extends [string | number, ...infer Rest]
// @ts-expect-error
? `${List[0]}${Delimiter}${Join<Rest,Delimiter>}` : string;