- 如何使用 TypeScript 实现与 call(或者 apply) 功能类似的函数,重在考察候选人对泛型的应用;
- 什么是泛型?泛型的作用是什么?重在考察候选人对泛型的理解。
什么是泛型?
泛型是指类型参数化,将某种具体的类型进行参数化。和定义函数参数是一样的的,我们可以给泛型定义若干个参数,当我们在调用时传入具体的参数。
泛型的作用是什么?
设计泛型的目的在于有效约束类型成员之间的关系,比如函数参数和返回值、类或者接口成员和方法之间的关系。
泛型类型参数
function ref<P>(p: P): P {
return p;
}
const a = ref<number>(1);
const b = ref<string>('1');
function reflectArray<P>(param: P[]) {
return param;
}
const reflectArr = reflectArray([1, '1']);
注意:函数的泛型入参必须和参数/参数成员建立有效的约束关系才有实际意义。
泛型类
泛型约束构造函数、方法的类型、属性
泛型类型
将类型入参的定义移动到类型别名或接口名称后,此时定义的一个接收具体类型入参后返回一个新类型的类型就是泛型类型。
const reflectFn: <P>(param: P) => P = reflect; // ok
type ReflectFuncton = <P>(param: P) => P;
interface IReflectFuncton {
<P>(param: P): P
}
const reflectFn2: ReflectFuncton = reflect;
const reflectFn3: IReflectFuncton = reflect;
type GenericReflectFunction<P> = (param: P) => P;
interface IGenericReflectFunction<P> {
(param: P): P;
}
const reflectFn4: GenericReflectFunction<string> = reflect; // 具象化泛型
const reflectFn5: IGenericReflectFunction<number> = reflect; // 具象化泛型
const reflectFn3Return = reflectFn4('string'); // 入参和返回值都必须是 string 类型
const reflectFn4Return = reflectFn5(1); // 入参和返回值都必须是 number 类型
type StringOrNumberArray<E> = E extends string | number ? E[] : E;
type StringArray = StringOrNumberArray<string>; // 类型是 string[]
type NumberArray = StringOrNumberArray<number>; // 类型是 number[]
type NeverGot = StringOrNumberArray<boolean>; // 类型是 boolean
注意:枚举类型不支持泛型。
泛型约束
限制参数类型
function get<P extends string | number | boolean>(p:P):P {
return p;
}
const e = get(1);
const f = get('1');
const g = get(!1);
function set<P extends {id: string, name: number}>(p:P):P {
return p;
}
const h = set({id: '1', name: 1})