1. 泛型是什么
泛型,顾名思义,就是能够实用于多个类型,应用类型变量比方 T 帮忙咱们捕捉传入的类型,之后咱们就能够持续应用这个类型。
如下定义了一个 identity 泛型函数,<T> 增加了类型变量 T,它就能够帮忙捕捉咱们传入的变量 value 的类型,而后再次应用 T 作为返回值类型,这样就束缚了参数类型和返回值类型是雷同的了。
function identity <T>(value: T) : T {return value;}
2. 泛型类型和泛型接口
const myIdentity: <T>(arg: T) => T = identity;
泛型类型和非泛型类型没有什么区别,只是传入了类型参数。
咱们还能够应用对象字面量的模式来申明函数类型:
const myIdentity: {<T>(arg: T): T } = identity;
这样就引入了泛型接口:
interface GenericIdentityFn {<T>(arg: T): T;
}
const myIdentity: GenericIdentityFn = identity;
再进一步把类型变量 T 作为接口的参数,应用接口的时候再传入类型参数,就锁定了函数中应用的类型:
interface GenericIdentityFn<T> {(arg: T): T;
}
const myIdentity: GenericIdentityFn<number> = identity;
3. 泛型类
在类名前面跟上类型变量,就能够在类中应用这些泛型类型。
class GenericPerson<T, U> {
name: T;
getAge: (age: U) => U;
}
let person = new GenericPerson<string, number>();
person.name = 'Jane';
person.getAge = function (x) {return x;};
person.getAge(2);
4. 何时应用泛型
当接口、函数或类要解决多种数据类型并且 在其中多个中央应用该类型 的时候。
5. 泛型束缚
通常用接口来形容约束条件,用 extends 实现束缚。
// 传入合乎束缚类型的值,必须蕴含 length 属性
interface Lengthwise {length: number;}
function loggingIdentity<T extends Lengthwise>(arg: T): T {console.log(arg.length);
return arg;
}
// 通过 K extends keyof T 确保参数 key 肯定是对象中含有的键,这样就不会产生运行时谬误
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {return obj[key];
}
6. 泛型条件类型
条件类型会以一个条件表达式进行类型关系检测,从而在两种类型中抉择其一:
T extends U ? X : Y
通常会联合推断关键字 infer 来应用:
type ParamType<T> = T extends (...args: infer P) => any ? P : T;
这样就能够实现类型抽取,如果 T 能够赋值给(…args: infer P) => any,那么返回参数 P,否则返回 T 自身的类型。