TypeScript学习笔记之二

80 阅读1分钟

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;