前言
软件工程中,可以使用
泛型来创建可重用的组件,一个组件可以支持多种类型的数据(TypeScript文档)
使用场景
泛型函数
const useRecord = <T>(initVal: T) => {
// 用类型变量T来接受任意类型
// T---一种特殊的变量,只用来表示类型而不是值
const [record, setRecord] = useState<T>(initVal);
const cassette = (val) => setRecord(val);
const undo = () => setRecord(undefined);
return {
cassette,
undo,
record,
};
};
- 泛型中的 T 就像一个占位符、或者说一个变量,在使用的时候可以把定义的类型像参数一样传入,它可以原封不动地输出
// TS 类型推断,自动推导出类型
const { record } = useRecord('123')
// 指定要使用的类型
const { record } = useRecord<{name: string, age: number}>({name: '123', age: 123})
泛型类型
type Partial<T> = {
[p in keyof T]?: T[p];
}
interface IPaginationFilter {
pageSize: number;
pageNo: number;
}
type IEntireFilter = Partial<ISearchFilter>;
- 使用Partial时传入一个类型参数来指定泛型类型
泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
+与接口一样,直接把泛型类型放在类后面,可以帮助我们确认类的所有属性都在使用相同的类型 +静态部分和实例部分。 泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型
泛型约束
export interface OrderExtraInfo {
// 收货码
receivingCode: string;
// 下单时间
createTime: MomentInput;
}
const checkHandle = <T>(v:T extends OrderExtraInfo) => {
const result = `收货码为${v.receivingCode},下单时间为{v.createTime}`
console.log(result);
return T;
}
- 在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性。这时候我们可以让泛型T继承某个接口,那么传递过来的类必须要有这个属性才能传递过来
总结
- 在定义函数,接口,类的时候,不预先指定具体的类型,而在使用的时候在去指定类型的一种特征
- 泛型的好处是使用时不必对类型进行强制转换,它通过编译器对类型进行检查;