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
版权声明:本文标题:ts 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1686891188h45320.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论