泛型
泛型:指的是类型参数化,即将原来某种具体的类型进行参数化。
- 可以给泛型定义若干个类型参数,并在调用时给泛型传入明确的类型参数。
- 目的: 有效约束类型成员之间的关系,如 函数参数和返回值、类或者接口成员和方法之间的关系
泛型类型参数
-
通过尖括号<>语法给函数定义一个泛型参数P,并指定param参数的类型为P
function reflect<P>(param: P){ return param } -
通过 <> 语法指定了类型入参
const reflectStr = reflect<string>('abc') // str的类型是string const reflectNum = reflect<number>(1) // num的类型是 number如果调用泛型函数时受泛型约束的参数有传值,泛型参数的入参可以从参数的类型中进行推断,而无需再显示指定类型(可缺省)
const reflectStr2 = reflect('abc') // str的类型是string -
泛型不仅可以约束函数整个参数的类型,还可以约束参数属性、成员的类型
function reflectArray<P>(param: P[]){ return param } const reflectArr = reflectArray([1, '1']) //reflectArr是 (string | number)[]注意:函数的泛型入参必须和参数、参数成员建立有效的约束关系才有实际意义
-
可以给函数定义任何个数的泛型入参
function reflect<P, Q>(p1: P, p2: Q): [P, Q]{ return [p1, p2] }
泛型类
-
在类的定义中,可以使用泛型来约束构造函数、属性、方法的类型
class Memory<S>{ store: S constructor(store: S){ this.store = store } set(store: S){ this.store = store } get(){ return this.store } } // 使用 const num = new Memory<number>(1) // <number> 可缺省 const str = new Memory('name') // <string>缺省 -
对 React 开发者而言,组件也支持泛型
function GenericCom<P>(props: {prop1: string}){ return ... } <GenericCom<{name: string }> prop1 = "1"/>
泛型类型
-
可以使用Array<类型>的语法来定义数组类型,Array本身就是一种类型。
-
在TS中,类型本身就可以被定义为拥有不明确的类型参数的泛型。并且可以接收明确类型作为入参,从而衍生出更具体的类型。
const reflectFn: <P>(params: P) => P = reflect-
可以把 reflectFn的类型注解提取为一个能被复用的类型别名或者接口:
// 提取为类型别名 type ReflectFunction = <P>(params: P) => P // 提取为接口 interface IReflectFunction { <P>(params: P): P } const reflectFn2: ReflectFunction = reflect const reflectFn3: IReflectFunction = reflect -
定义了两个可以接收参数P的泛型类型
type ReflectFunction<P> = (params: P) => P interface IReflectFunction<P>{ (params: P): P } const reflectFn4: ReflectFunction<string> = reflect const reflectFn5: IReflectFunction<number> = reflect -
可以使用一些类型操作符进行运算表达,使得泛型可以根据入参的类型衍生出各异的类型
type StrOrNumArray<E> = E extends string | number ? E[] : E type StrArray = StrOrNumArray<string> //类型是 string[] type NumArray = StrOrNumArray<number> //类型是 number[] type NoArray = StrOrNumArray<boolean> //类型是 boolean -
分配条件类型:在条件类型判断的情况下,如果入参的是联合类型,则会被拆解成一个个独立的(原子)类型(成员)进行类型运算。
-
利用泛型,我们可以抽象封装出很多有用、复制的类型约束
interface ReduxModel<State> { state: State, reducers: { [action: string]: (state: State, action: any) => State } }枚举类型不支持泛型
-
泛型约束
-
可以把泛型入参限定在一个相对更明确的集合内,以便对入参进行约束
-
可以使用 “泛型入参名 extends 类型”语法达到这个目的
function reflect<P extends number|string|boolean>(param: P): P{ return param } -
可以把接口泛型入参约束在特定的范围内
interface ReduxModel<State extends {id: number, name: string}>{ state: State } -
可以在多个不同的泛型入参之间设置约束关系
interface ObjSetter { <O extends {}, K extends keyof O, V extends O[K]>(obj: O, key: K, value: V): V } const setValueOfObj: ObjSetter = (obj, key, value) => (obj[key] = value) -
可以给泛型入参指定默认值(默认类型),且语法和指定函数默认参数完全一致
interface ReduxModel2<State = {id: number, name: string}>{ state: State } -
泛型入参的约束与默认值可以组合使用
interface ReduxModelMixed<State extends {} = {id: number, name: string}>{ state: State }
-