admin 管理员组

文章数量: 887021

ts

typeScript 泛型

/*** typeScript 学习5 泛型*  泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性*  泛型变量: <泛型变量1, ...>*  * 常用的几个命名含义:*  * T 代表类型(type), *  * K 代表对象中的键类型(Key), *  * V 代表对象中的值类型(Value),*  * E 代表元素类型(Element) ,*  * U *  泛型接口: interface 接口名<泛型变量1 [extends 类型 | keyof 类型],....> {}*  泛型类: class 类名 <泛型变量1 [extends 类型 | keyof 类型], ...>*  泛型约束:*  * extends 关键字: 用于类型的继承或者条件判断,当与三目运算符(?:)使用的时候是条件判断;其他情况都是继承*  *  继承/扩展类型: 继承父类的方法和属性,扩展用于接口继承*  *  泛型约束: *  *  *  <U extends T> U 必须满足 T                       // 可以理解为继承 U 继承了 T*  *  *  keyof关键字: <T, U exindes keyof T>  U 必须属于T的 *  *  条件类型与高阶类型: 可以用来判断一个类型是否是分配给另一个类型的 *  *  * A extends B ? 'x' : 'y', 此处是分配 要求 A 中拥有 B 中所有的约束 如果满足 返回 x 否则返回 y*  *  * 分配条件类型: 对于使用 extends 关键字的条件类型(三元),如果 extends 前面的参数是一个泛型,*        且传入这个参数的是一个联合类型,那么则将联合类型拆开分别匹配(分配律) 然后将结果联合返回(返回值是一个联合类型)*  *  * never是特殊的, "never被认为是空的联合类型", 但是因为没有满足联合项可以分配, 所以根本不会执行分配,会返回原值 never*  *  * 防止条件判断中的分配: 将泛型参数用 [] 括起来, 这样传入的参数将作为一个整体*  索引类型: *  *  索引类型的查询操作符: keyof T       表示类型T的所有公共属性的字面量的联合类型示*  *  索引访问操作符:T[K]               表示对象T的属性K所代表的类型*  映射类型: [P in 需要被遍历的类型]: 返回值类*  *  ?: 可选属性*  *  -: 移除*  *  readonly: 只读                   readonly [P in T]: P*  预定义的有条件类型*  变量?.属性或方法: 相当于 三元运算 判断这个变量中这个属性是否为空或未定义           obj?. y 意思为 x可能为 null,undefined*//*** extends 关键字*/
type Human = { name: string; occupation: string; }
type Duck = { name: string; }
// 验证 Duck 是否满足 Human 中的所有约束 如果满足返回 yes 不满足返回 no
type Bool = Duck extends Human ? 'yes' : 'no'; // Bool => 'no'type A1 = 'x' extends 'x' ? string : number; // A1 => string
type A2 = 'x' | 'y' extends 'x' ? string : number; // A2 => number// 因为此处 extends 条件判断 使用了泛型而且没设置条件阻断 所以但 传过来的 类型是 联合类型的时候,
// 会将联合类型拆开 分别匹配然后将结果重新组合成联合类型 返回
type P<T> = T extends 'x' ? string : number;
type A3 = P<'x' | 'y'>; // string | numbertype A4 = never extends 'x' ? string : number; // string
// never被认为是空的联合类型但是因为没有满足联合项可以分配, 所以不会执行会直接返回原值 never
type A5 = P<never>; // never// 防止条件判断中的分配: 将泛型参数用 [] 括起来, 这样传入的参数将作为一个整体
type M<T> = [T] extends ['x'] ? string : number;
type A6 = M<'x' | 'y'>; // number
type A7 = M<never>; // string/*** 索引类型*  索引类型的查询操作符: keyof      keyof T 表示类型T的所有公共属性的字面量的联合类型示*  索引访问操作符:T[K]            表示对象T的属性K所代表的类型*/interface Obj_1 {name: string;sex: boolean;}// 定义变量key,类型为keyof Objlet key: keyof Obj_1;let keys: Obj_1['sex'];/*** 映射类型*  { [ P in K ]: T }*  { [ P in K ]?: T }*  { [ P in K ]-: T }*  { readonly [ P in K ]: T }*  { readonly [ P in K ]?: T }*  { -readonly [ P in K ]?: T }*  [P in K] 注: P 为变量 类似于 for in中定义在in前方的i K 是需要遍历的数组或对象 *  [P in K]  遍历目标类型的公开属性名; 类似 for in*  is 判断变量是否属于某个类型可以理解为 !!*  infer: 条件类型中的类型推断 需要和三目运算或extends同时使用*  映射类型: 将原有的对象类型映射成新的对象类型 可以理解为对key和value 的操作*  *  可选属性: Partial<T>                                         // 将必选属性变成可选属性*  * 源码: type Partial<T> = { [P in keyof T]?: T[P] }*  只读属性:Readonly<T>                                        // 将非只读属性转换成只读属性*  * 源码:type Readonly<T> { readonly [P in keyof T]: T[P] }   *  动态构造:Record<K extends keyof any, T>                     // 以typeof格式快速创建类型*  * 源码:type Record<K extends keyof any, T> = { [P in K]: T }*  选择/挑选属性: Pick<类型,需要被取出的属性>                    // 从定义的属性中取出一组属性返回*  * 源码:type Pick<T, K extends keyof T> = { [P in K]: T[P] }*  必选属性: Required<T>*  * 源码:type Required<T> = { [P in keyof T]-?: T[P]; }*  排除属性: Exclude<T, U>*  * 源码:type Exclude<T, U> = T extends U ? never : T*  提取属性: Extract<T, U>*  * 源码:type Extract<T, U> = T extends U ? T : never*  忽略属性:Omit<T, K>*  * 源码:type Omit<T, K extends string | number | symbol> = { [P in Exclude<keyof T, K>]: T[P]; }*  排除null和undefined:NonNullable<T>*  * 源码:type NonNullable<T> = T extends null | undefined ? never : T*  获取函数参数返回类型:Parameters<T>*  * 源码:type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never*  获取函数返回类型:ReturnType<T>*  * 源码:type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;*/ type A8<T> = {[P in keyof T]?: T[P]
}
interface Obj_2 { name: string }type A9 = A8<Obj_2>; // type = { name?: string | undefined}
type A10 = {         // type A10 = { x ?: number | undefied; ... } [P in 'x' |'y']?: number | undefined;
}type A11 = {a?: string;b?: number;c?: boolean;
}// 可以简写为 type A11Key = keyof A11;
type A11Key = 'a' | 'b' | 'c';
type A12 = { [K in A11Key]: A11[K] };   // A12 = { a: string; ... }// A11 -> A12 步骤可以简化为
type A13 = { [K in keyof A11]:A11[K] }; // 与 A12 结果一样
// 也可以写成这样
type A14<P> = { [K in keyof P]: P[K] }; //
type A15 = A14<A11>;                    // 与 A12 结果一样/*** 泛型接口*  interface <泛型变量> {}*/
interface generic_interface_1<T> {name: T;sex: T;age: number,
}
const generic_var_1:generic_interface_1<string> = {name: "wzy",// 报错 不能将 布尔类型分配给 string 这是因为 上面传递的类型是 string类型 // 如果需要使用 布尔类型可以传递一个联合类型 或者修改接口// sex: false, sex: "女",age: 16,
}
const generic_var_2:generic_interface_1<string | boolean> = {name: "wzy",sex: false, // 不报错了age: 18
}// 定义函数的形式
interface generic_interface_2 {<T>(length:number, value: T): Array<T>;
}
const generic_var_3: generic_interface_2 = function<T>(length:number, value: T):Array<T>{let arr: T[] = [value];return arr;
}
// 将T提前到接口
interface generic_interface_3<T> {(length:number, value: T): Array<T>;
}const generic_var_4: generic_interface_3<string> = function <T>(length:number, value: T): Array<T>{let arr: T[] = [value];return arr;
}
console.log(generic_var_4(12, "24"));/*** 泛型类*  class 类名 <泛型变量> {}*  new 类名<类型>();*/class generic_class_1<T> {public list:T[] = [];add(value: T): void {}minNumber(value: T): T {return value;}
}
const generic_var_5 =  new generic_class_1<number>()// 意思是 类型T 必须满足 any
class generic_class_2 <T extends Record<string, any>>{private _studentsArray: Array<T>= [];delete<K extends keyof T>(key: K, value: string): void {for(let item in this._studentsArray){if (this._studentsArray[item]?.[key] == value) {this._studentsArray.splice(Number(item), 1);}}}
}type x25 = {name: string;sex: number;
}
type x05 = Record<keyof x25, number>/*** 泛型约束*  在函数内使用 泛型类型的变量的时候因为不知道 变量具体的类型 所以无法使用变量的方法和属性*  泛型约束: <泛型变量 extends 需要被满足的约束> *  多个参数之间的约束: <泛型变量1, 泛型变量2 extends 泛型变量1 >*  keyof关键字:能够获取一个 interface 或对象 的全部 key 也可以获取变量的类型*/// 约束
interface i1 {name: string;sex: boolean;
}
type ob = {name: "wzy"}function funs<T, U extends keyof T>(param: T){console.log(param);
}
funs<i1, `name`>({name: "wzy", sex: false})type xxxx = keyof {name: string, value: string, key: string | number}; // 限制函数参数和返回值类型
//  泛型约束:在函数内部使用类型为泛型变量的变量的时候,因为泛型的原因不确定变量是什么类型,所以不能随意操作属性和方法
function generic_fun_1<T>(value: T): T{// console.log(value.length); // 报错 类型“T”上不存在属性“length”。return value;
}
console.log(generic_fun_1<string>("string"));function generic_fun_1s<T extends string>(value: T): T{console.log(value.length); // 限制没有报错了return value;
}// 限制构造函数参数类型以及成员变量、方法参数的类型
class generic_class_3 <T>{name: T;constructor(name: T){this.name = name;}action(say: T): T {return say;}
}
const generic_var_6 = new generic_class_3<string>("限制");
console.log(generic_var_6?.action("0556"));// 定义多个泛型变量
function generic_fun_2<T, U>(tuple: [T, U]): [U, T]{return [tuple[1], tuple[0]];
}
console.log(generic_fun_2<string, number>(["xy", 11]));// 泛型变量的默认值
function generic_fun_3<T = string>(){} 
generic_fun_3()/*** 预定义的有条件类型*  Exclude<T, U> -- 从T中剔除可以赋值给U的类型。*  Extract<T, U> -- 提取T中可以赋值给U的类型。*  NonNullable<T> -- 从T中剔除null和undefined。*  ReturnType<T> -- 获取函数返回值类型。*  InstanceType<T> -- 获取构造函数类型的实例类型。*/

本文标签: ts