Appearance
前言
新坑,TS类型编程学习
知识记录
any 和 unknown区别
any可以接受任何值,也可以赋值 unknown可以接受任何值,但是不能赋值给any和unknown之外的类型
keyof 用于把索引类型变成联合类型
ts
interface Person {
name: string
age: number;
}
type Test = keyof Person // "name" | "age"
type Test1 = "name" extends keyof Person ? true : false // true
const a: Test = "name"extends 详解
满足下面条件,判断为true
- 两边类型都是常量时,常量需要相同
- 两边都是基础类型时,类型需要相同
- 索引类型,需要操作符左边包含操作符右边
- 联合类型,满足其中一个即可。
- 交叉类型需要全部满足
ts
interface Pig {
type: 'pig',
weight: number
}
interface Animal {
type: string
}
type Test = Pig extends Animal ? true : false // true联合类型和交叉类型
联合类型
- 针对基础类型时,表示的是几个类型任意一个。
- 联合类型只能调用共同方法
交叉类型
- 针对基础类型和常量类型
ts
string & boolean // never
string & string // string
string & (string | boolean) // string- 针对索引类型, 表示的索引合集,需要同时满足所有。
ts
interface A {
name: string
}
interface B {
age: number
}
type Test = A & B; // A需要同时具有name 和 age属性工具类
IsEqual
ts
// 简单版本
type IsEqual1<A, B> = A extends B ? B extends A ? true : false : false
type Test = IsEqual1<string, string> // true
type Test1 = IsEqual1<string, '1'> // false
type Test2 = IsEqual1<string, string | boolean> // boolean !!! 失效
// 升级版本
type IsEqual12<A, B> = [A] extends [B] ? [B] extends [A] ? true : false : false
type Test3 = IsEqual12<string, string> // true
type Test4 = IsEqual12<string, '1'> // false
type Test5 = IsEqual12<string, string | boolean> // false
type Test6 = IsEqual12<{
name: string
}, {
readonly name: string,
}> // true !!!!! 失败
// 最终版本
type IsEqual<A, B> = (<T>() => T extends A ? 1 : 2 ) extends (<T>() => T extends B ? 1 : 2) ? true : false
type Test7 = IsEqual<{
name: string
}, {
readonly name: string,
}> // false元组
提取元组的第一个数组类型
ts
type GetCupleFirstType<T extends unknown[]> = T extends [infer FirstType, ...unknown[]] ? FirstType : never;
type Test = GetCupleFirstType<[string, number, symbol]> // Test = string提取元组的最后一个类型
ts
type GetLastCupleType<T extends unknown[]> = T extends [...unknown[], infer Last] ? Last : never
type Test = GetLastCupleType<[string, number, symbol]> // Test = symbol数组Pop
ts
type Pop<T extends unknown[]> = T extends [...infer Rest, unknown] ? Rest : never;
type Test = Pop<[string, boolean, symbol]> // [string, boolean]数组Push
ts
type Push<T extends unknown[], S> = [...T, S]
type Test = Push<[boolean], string> // [boolean, string]数组Shift
ts
type Shift<T extends unknown[]> = T extends [any, ...infer Rest] ? Rest : never
type Test = Shift<[unknown, boolean, '1']> // [boolean, '1']数组Unshift
ts
type Unshift<T extends unknown[], S> = [S, ...T]
type Test = Unshift<[boolean], string> // [string, boolean]数组concat
ts
type Concat<T extends unknown[], S extends unknown[]> = [...T, ...S]
type Test = Concat<[boolean, string], ['1', '2']> // [boolean, string, '1', '2']数组zip
ts
type Zip<One extends [unknown, unknown], Other extends [unknown, unknown]> = One extends [infer OneFirst, infer OneAnother] ? Other extends [infer OtherFirst, infer OtherAnother] ? [[OneFirst, OtherFirst], [OneAnother, OtherAnother]]: [] : []
type Test = Zip<['1', '2'], ['3', '4']> // [['1', '3'], ['2', '4']]任意长度数组合并 zip2
ts
type Zip2<One extends unknown[], Second extends unknown[]> = One extends [infer OneFirst, ...infer OneRest] ? Second extends [infer SecondFirst, ...infer SecondRest] ? [[OneFirst, SecondFirst], ...Zip2<OneRest, SecondRest>] : [[OneFirst], ...Zip2<OneRest, []>] : Second extends [infer SecondFirst, ...infer SecondRest] ? [SecondFirst, ...Zip2<SecondRest, []>] : []
type Test = Zip2<["1", "2", "4"], ["5", "6", "7" ,"1"]>数组反转
ts
type ReverseHelper<T extends unknown[], R extends unknown[] = []> = T extends [infer First, ...infer Rest] ? ReverseHelper<Rest, [First, ...R]> : R
type Reverse<T extends unknown[]> = ReverseHelper<T>
type Test = Reverse<['1']>数组flat
ts
type ArrayFlat<T, R extends unknown[] = []> = T extends [infer First, ...infer Rest] ? ArrayFlat<Rest, [...R, ...ArrayFlat<First>]> : [...R, ...(T extends unknown[] ? T : [T])]
type Test = ArrayFlat<[1| 5 | 2]> // 为啥是 1 | 5 | 2字符串
字符串 startWith
ts
type StartWith<T extends string, S extends string> = T extends `${S}${string}` ? true : false // ts只有字符串,没char,所以用string匹配
type Test = StartWith<"123", "1"> // true字符串EndWith
ts
type EndWith<S extends string, T extends string> = S extends `${string}${T}` ? true : false;
type Test = EndWith<"123", "3"> // true
type Test1 = EndWith<"123", "4"> // false字符串首位字符串
ts
type GetFirstString<T extends string> = T extends `${infer First}${string}` ? First : never // infer 定义的变量只能在true里面使用
type Test = GetFirstString<"123"> // "1"替换字符串
ts
type Replace<S extends string, T extends string, R extends string> = S extends `${infer Prev}${T}${infer After}` ? `${Prev}${R}${After}` : S
type Test = Replace<"123", "2", "3"> // "133"
type Test1 = Replace<"123", "3", "2"> // "133"创建指定长度的字符串
ts
字符串Trim
ts
type Space = '\n' | ' ' | '\t'
type TrimLeft<S extends string> = S extends `${Space}${infer Rest}` ? TrimLeft<Rest> : S
type TrimRight<S extends string> = S extends `${infer Rest}${Space}` ? TrimRight<Rest> : S
type Trim<S extends string> = TrimLeft<TrimRight<S>>
type Test = Trim<" 123\n\t">首字母转大写
ts
type UpcaseFirst<S extends string> = S extends `${infer First}${infer Rest}` ? `${Uppercase<First>}${Rest}` : S;
type Test = UpcaseFirst<'ceshi'> // "Ceshi"转小驼峰
ts
type CamelCase<S extends string> = S extends `${infer Prev}_${infer AfterFirst}${infer Rest}` ? `${Prev}${Uppercase<AfterFirst>}${CamelCase<Rest>}` : S
type A = CamelCase<'dong_test_liu'>删除指定字符串
ts
type DropStr<S extends string, T extends string> = S extends `${infer Prefix}${T}${infer Suffix}` ? DropStr<`${Prefix}${Suffix}`, T> : S
type Test = DropStr<'123', '1'> // '23'函数
获取函数参数类型
ts
type GetParamsType<F extends Function> = F extends (...args: infer Args) => any ? Args : []
type Test= GetParamsType<(a?: string) => any> // [a?: string]获取函数返回参数类型
ts
type GetReturnType<F extends Function> = F extends (...args: any[]) => infer Return ? Return : never // args中需要设置any,不能是unknow
type Test = GetReturnType<(a: string, b: number) => string> // string添加函数参数
ts
type GetParamsType<F extends Function> = F extends (...args: infer Args) => any ? Args : [];
type GetReturnType<F extends Function> = F extends (...args: any[]) => infer Return ? Return : never;
type AddFunctionParams<F extends (...args: any[]) => any, T> = (...args: [...GetParamsType<F>, T]) => GetReturnType<F>;
type AddFunctionParams1<F extends (...args: any[]) => any, T> = F extends (...args: infer Args) => infer ReturnType ? (...args: [...Args, T]) => ReturnType : F
type Test = AddFunctionParams1<(a: string) => string, string>设置函数中this的类型
通过函数参数中第一个参数this定义类型
ts
interface Person {
name: string
say(name: string): any
}
interface SayName {
(this: Person): any
}
const a: SayName = function () {
console.log(this.say('name is yang'))
}
const person: Person = {
name: 'yang',
say(name: string) {
console.log(name)
},
}
a() // Error
a.call(person)
const b = a.bind(person)
b()获取函数中this指向的类型。
ts
type GetThisType<T extends Function> = T extends (this: infer ThisType, ...args: any[]) => any ? ThisType : never // 注意,函数参数要用 any[] 接受
type Test = GetThisType<(this: string, name: boolean) => boolean> // string构造器和类实例
ts
interface Person {
name: string
}
interface PersonCtor {
new (name: string): Person
}
const createPerson: Person = function(ctor: PersonCtor) {
ctor() // 禁止 非构造函数调用
return new ctor('name');
}获取构造器的实例类型
ts
// 获取构造函数的函数实列
type GetInstanceType<T extends new (...args: any[]) => any > = T extends new (...args: any[]) => infer InstanceType ? InstanceType : unknown
interface Person {
name: string
}
interface PersonCtor {
new (): Person
}
type Test = GetInstanceType<PersonCtor> // Person获取函数构造器参数
ts
// 获取构造函数的参数类型
type GetInstanceType<T extends new (...args: any[]) => any > = T extends new (...args: infer ParamsType) => any ? ParamsType : unknown
interface Person {
name: string
}
interface PersonCtor {
new (name: boolean): Person
}
type Test = GetInstanceType<PersonCtor> // [name: boolean]获取索引类型中指定值的类型
ts
interface Person {
name: boolean
age: number
}
type GetPropNameType<T> = 'name' extends keyof T ? T extends { name: infer NameType } ? NameType : never : never
type Test = GetPropNameType<Person> // boolean索引类型值修改
ts
type ChangeValue<T> = {
[K in keyof T]: [T[K]]
}
interface Person {
name: string
age: number
}
type Test = ChangeValue<Person>索引类型索引修改
ts
type ChangeIndex<T> = {
[K in keyof T as Uppercase<K & string>]: [T[K]] // 只过滤 string类型, 交叉类型在针对普通类型时需要严格相同, 同时never索引默认不会展示
}
interface Person {
name: string
age: number
1: number
}
type Test = ChangeIndex<Person> // {NAME: string, age: number} 无 1: numberRecord
ts
type MyRecord<S extends string | number | symbol, T> = {
[K in S ]: T
}
type A = MyRecord<string | 1, number>取出值为指定类型的索引
ts
type Mypick<Obj, T> = {
[K in keyof Obj as Obj[k] extends T ? K : never] : Obj[K]
}
type A = {
sex: number
}
type Test = Mypick<{
name: string;
age: number;
sex: A
}, A | string> // { name: string; sex: A }readonly
ts
type MyReadOnly<T> = {
readonly [K in keyof T]: T[K]
}
type Test = MyReadOnly<{
name: string;
age?: number
}>ToPartial 全部可选
ts
type ToPartial<T> = {
[K in keyof T]?: T[K]
}
type Test = ToPartial<{
name: string
age?: number
}>去掉readonly
ts
type DropReadOnly<T extends Object> = {
-readonly [K in keyof T]: T[K]
}
type Test = DropReadOnly<{
readonly name: string;
age: number
}>去掉可选
ts
type DropOptional<T extends Object> = {
[K in keyof T]-?: T[K]
}
type Test = DropOptional<{
name?: string;
age: number
}>获取指定索引类型的子集
ts
type FilterByIndexType<Obj extends Object, T extends number | string | symbol> = {
[K in keyof Obj as K & T]: Obj[K]
}
type A = FilterByIndexType<{
[x: symbol]: number
name: string
1: string
2: number
}, symbol | 1>
type ReverseHelper<T extends unknown[], R extends unknown[] = []> = T extends [infer First, ...infer Rest] ? ReverseHelper<Rest, [First, ...R]> : R
type Reverse<T extends unknown[]> = ReverseHelper<T>
type Test = Reverse<['1']>type B = 1 & (number | string)获取指定指针类型的子集
ts
type FilterValueType<Obj extends Object, T extends number | string | symbol> = {
[K in keyof Obj as Obj[K] extends T ? K :never]: Obj[K]
}
type Test = FilterValueType<{
name: string;
age: 18
}, number>循环
递归获取promise返回值类型
ts
type DeepPromiseTypeHelper<P> = P extends Promise<infer ValueType> ? DeepPromiseTypeHelper<ValueType> : P
type DeepPromiseType<P extends Promise<unknown>> = DeepPromiseTypeHelper<P>
type Test = DeepPromiseType<Promise<number>>反转
是否包含
ts
type IsEqual<A, B> = (<T>() => T extends A ? 1 : 2 ) extends (<T>() => T extends B ? 1 : 2) ? true : false
type Include<S extends unknown[], T> = S extends [infer First, ...infer Rest] ? IsEqual<First, T> extends true ? true : Include<Rest, T> : false
type A = Include<['1' | '2', '2'], '2' | '1'>pick、omit和Exclude
ts
type MyExclude<T extends keyof any, K extends keyof any> = T extends K ? never : T;
type test1 = MyExclude<1 | 2 | 3, 3> // 1 | 2 利用了分布式条件语句
type MyPick<T extends Record<keyof any, unknown>, K extends keyof T = keyof T> = {
[P in K]: T[P]
}
type MyOmit<T extends Record<keyof any,unknown>, K extends keyof any> = MyPick<T, MyExclude<keyof T, K>>
type test = MyOmit<{
age: string;
name: number
}, 'age'>getByPropType、getByPropValue
ts
type GetPropsByType<T extends object, K> = {
[P in keyof T]: T[P] extends K ? P : never
}[keyof T]
type PickByPropType<T extends object, K> = Pick<T, GetPropsByType<T, K>>
type OmitByPropType<T extends object,K> = Omit<T, GetPropsByType<T, K>>互斥的联合类型
因为结构类型的存在,联合类型不能很好的做到互斥(复杂类型),比如下面
ts
type A = {
age: string
}
type B = {
name: number;
}
type C = A | B;
const test: C = { // 无法做到只能A或者B
age: '1';
name: 1
}
// 改进如下
type WithOut<T, U> = {
[K in Exclude<keyof U, keyof T>]: never;
} & T元组和联合类型相互转换
T[number]
错题分析
写一个链式的对象
判断是否是联合类型
ts
type IsUnion<T, U = T> = [T] extends [never] ? false : ( // 单独一个never,使用包裹避免分布式条件语句
T extends U ? Exclude<U, T> extends never ? false : true : true
);