泛型

68 阅读2分钟

前言

软件工程中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据(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继承某个接口,那么传递过来的类必须要有这个属性才能传递过来
总结
  • 在定义函数,接口,类的时候,不预先指定具体的类型,而在使用的时候在去指定类型的一种特征
  • 泛型的好处是使用时不必对类型进行强制转换,它通过编译器对类型进行检查;