站群软件,百度指数在线查询小程序,广州网站建设骏域,网站建设管理工作目录 概念导读泛型函数多个泛型参数泛型约束泛型别名泛型接口泛型类总结#xff1a; 概念导读 泛型#xff08;Generics#xff09;是指在定义函数、接口或类的时候#xff0c;不预先指定具体的类型#xff0c;而在使用的时候再指定类型的一种特性。使用泛型 可以复用类型… 目录 概念导读泛型函数多个泛型参数泛型约束泛型别名泛型接口泛型类总结 概念导读 泛型Generics是指在定义函数、接口或类的时候不预先指定具体的类型而在使用的时候再指定类型的一种特性。使用泛型 可以复用类型并且让类型更加灵活 泛型实现类型参数化 在定义这个函数时, 我不决定这些参数的类型 而是让调用者以参数的形式告知我这里的函数参数应该是什么类型 把类型作为参数放在尖括号中 泛型的基本使用
案例讲解 当我们封装一个函数的时候可能由于业务需求的不同向函数内传递的参数类型也不相同。而TS 的语法规范是在函数定义的时候就需要为每个待接收的形参以及函数的返回值指定类型如果在我们调用执行函数之前就将类型给指定死了的话这就大大降低了函数的复用性了。 这时候,就可以使用 泛型来实现这样的需求将函数所需参数的类型延后到当我调用函数的时候可以根据不同的业务需求再指定其参数类型。这样一来将大大的提高函数的复用灵活性。 如下案例
泛型函数
普通函数定义法
function createArrayT(length: number, value: T): ArrayT {let result: T[] [];for (let i 0; i length; i) {result[i] value;}return result;
}createArray(3, x); // [x, x, x]箭头函数定义法
let append T(val: T, num: number): ArrayT {const arr: T[] []for (let index 0; index num; index) {arr.push(val)}return arr;
}
console.log(appendstring(一段字符串, 9));
//[一段字符串, 一段字符串, 一段字符串, 一段字符串, 一段字符串, 一段字符串, 一段字符串, 一段字符串, 一段字符串]
console.log(appendnumber(10086, 9));
//[10086, 10086, 10086, 10086, 10086, 10086, 10086, 10086, 10086] 我们在函数名后添加了 T 其中 T 用来指代任意输入的类型泛型后面的参数类型以及函数返回值的类型都可以 使用 T 泛型来定义站位。 console.log(append string (一段字符串, 9)); 在函数调用的时候再为其指定泛型所具体代表的类型也可以不手动指定而让类型推论自动推算出来推荐手动指定使其代码更加清晰明了 多个泛型参数 定义泛型的时候可以一次定义多个类型参数同样的在调用的时候再为其指定参数类型多泛型参数多用于元组类型的数据处理 普通函数写法
function swapT, U(tuple: [T, U]): [U, T] {return [tuple[1], tuple[0]];
}console.log(swapnumber, string([7, seven]));箭头函数写法
let swap T, U(tuple: [T, U]): [U, T] {return [tuple[1], tuple[0]];
}console.log(swapstring, number([字符串, 100]));泛型约束 由于泛型表示数据的类型的待定的由于事先不知道它是哪种类型所以不能够随意操作一个待定数据类型身上的方法属性如果传进来的数据类型没有这个属性方法则就会引起报错。 如下案例
function loggingIdentityT(arg: T): T {console.log(arg.length);return arg;
}// 报错: index.ts(2,19): error TS2339: Property length does not exist on type T.上例中泛型 T 不一定包含属性 length所以编译的时候报错了。
这时候我们就可以通过接口对泛型进行约束只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束
interface Lengthwise {length: number;
}function loggingIdentityT extends Lengthwise(arg: T): T {console.log(arg.length);return arg;
}上例中我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状也就是必须包含 length 属性。
此时如果调用 loggingIdentity 函数的时候传入的 arg 数据类型身上 不包含 length 属性那么在编译阶段就会报错了这样一来就大大降低了会发生在函数体内部的错误了。
补充
多个类型的参数之间也可以互相约束
function copyFieldsT extends U, U(target: T, source: U): T {for (let id in source) {target[id] (Tsource)[id];}return target;
}let x { a: 1, b: 2, c: 3, d: 4 };copyFields(x, { b: 10, d: 20 });上例中我们使用了两个类型参数其中要求 T 继承 U也相当于U 约束了 T 这样就保证了 U 上不会出现 T 中不存在的字段。 泛型别名
在类型别名 type 的后面使用T即可声明一个泛型参数接口里的其他成员都能使用该参数的类型
type len {length: number
}let fun T extends len(x: T): number {return x.length
}
console.log(funstring(486789413));//9泛型接口 前面提到过 interface 是我们在使用 TypeScript 的时候用来定义接口的关键字。 如
interface Person {name: string;age: number;
}
const dome: Person {name: sunny,age: 18,
};上面示例的代码中用声明接口限制了一个对象我们也可以通过泛型对我们的接口进行改造。 这时候我们通过定义泛型的方式定义 T U 两个占位符使得我们的接口具备了泛型更加灵活。但是我们发现 泛型接口和泛型函数不一样像上图中这样使用有一个地方报错了提示我们需要传入类型参数而不能依赖自动的类型推断来确实对象属性的类型其实这也是可以理解因为我们对一个对象的限制主要就是限制对象的属性类型如果我们不确定类型那我们传入的一切类型都是有效的了。就起不到类型的限制而前面我们使用泛型函数虽然没有显示声明类型但是我们达到了对函数入参和出参进行了统一。 interface PersonT, U {name: T;age: U;
}
const dome: Personstring, number {name: sunny,age: 18,
};所以定义泛型接口的时候正确的写法应该是 对其传入了两个确定的类型。TU的类型也因此确定了。
泛型接口来约束函数
interface PersonT {(value: T): ArrayT
}const printFun: Personstring T(value: T): ArrayT {let arr: T[] [];arr.push(value)return arr;
};
console.log(printFun(233)); //[233]泛型类
与泛型接口类似泛型也可以用于类的类型定义中
class informationT, U{name: Tage: Uconstructor(name: T, age: U) {this.name name;this.age age}
}
let c new informationstring, number(张三, 48)泛型参数的默认类型 在 TypeScript 2.3 以后我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数从实际值参数中也无法推测出时这个默认类型就会起作用。 class informationT string, U number{name: Tage: Uconstructor(name: T, age: U) {this.name name;this.age age}
}
let c new information(李四, 25)总结
泛型德优势是什么
增加类型的复用性和灵活性。
泛型实现的基本方法是什么
找到不确定类型的部分为其定义泛型参数传入参数时为泛型指定具体的类型
泛型约束的作用是什么
既可以保留泛型的灵活性又限制了一定的规范。 注明在正式开发中泛型的使用场景非常多… ♂️ 博主座右铭向阳而生我还在路上 —————————————————————————————— 博主想说将持续性为社区输出自己的资源同时也见证自己的进步 —————————————————————————————— ♂️ 如果都看到这了博主希望留下你的足迹【收藏点赞✍️评论】 ——————————————————————————————