泛型
声明: 这篇文章可能没有任何意义,因为代码实例都是官网上的
本人只是边学习,边记录过程,以及进行改写。如有不明,可直接移步官方文档
初识泛型
官方的两个例子
例子一:我们使用any
类型来定义函数:输入任意类型的参数,返回任意类型的值
function identity(arg: any): any {
return arg;
}
console.log(identity(100)); // 100
使用any
类型会导致这个函数可以接收任何类型的arg
参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。如果我们传入一个数字,我们只知道任何类型的值都有可能被返回。
例子二:改写一下
function identity(arg: number): number {
return arg;
}
console.log(identity(100)); // 100
此时我们只能传入number类型的数据 ,返回的也是number
但是,我们要的效果是,传入一种数据类型的参数,返回的只能是那种,可我们将他固定为number显然不合适。比如我们要求string也适合
此时我们引入 类型变量 T
function identity<T>(arg: T): T {
return arg;
}
此时我们可以想获取自己想要的任何类型 如下:我们传入的参数是string类型,返回的也是string类型
let id: string = identity<string>("hello world");
console.log(id); // hello world
也可以直接使用类型推断,简略代码
// let id:number = identity<number>(101010);
let id = identity(101010); // // 等同于上一行代码 类型推断
console.log(id)
个人觉得还是长一点具有可读性,不需要编译器进行类型推断。既然使用了typescript
,自然要让它看起来更严格。
使用泛型变量
泛型的数组, 打印它的长度
function fun<T>(arg: T[]): void {
console.log(arg.length)
}
// fun<number>([1,2,4]); // 3
fun<string>(['a','b','c', 'd']); // 4
函数类型
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: <T>(arg: T) => T = identity;
等同于js中的
function identity(arg) {
return arg;
}
let myIdentity = identity;
其实就是函数声明和使用
或许下面这样写更让我明白
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: {<T>(arg: T): T} = identity;
泛型的接口
上面一个列子
其实这个完全可以用接口去声明。
官方代码
字面量拿出来做为一个接口
interface GenericIdentityFn {
<T>(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn = identity;
再者,把泛型参数当作整个接口的一个参数
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
等同于下面这个代码
interface GenericIdentityFn<T> {
(arg: T): T;
}
let myIdentity: GenericIdentityFn<number> = function <T>(arg: T): T {
return arg;
}
就是函数的声明
使用这个函数,用变量来接受这个函数的返回值
// let id: string = myIdentity('102'); // Argument of type '"102"' is not assignable to parameter of type 'number'.
let id: number = myIdentity(102);
console.log(id)
泛型类
class GenericNumber<T> {
zeroValue: T;
add: {(x: T, y: T): T}; // 方法名 参数 返回值类型
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x:number, y:number) { return x + y; };
let sum = myGenericNumber.add(1,3);
console.log(sum); // 4
泛型约束
// 泛型约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:
loggingIdentity(3); // Error, number doesn't have a .length property
我们需要传入符合约束类型的值,必须包含必须的属性:
loggingIdentity({length: 10, value: 3});
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。