泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性,主要在用typescript时可以实现类型推导,不需要人为的每个地方去约束类型。
function foo<T>(params: T): T {
return params;
interface Params<T> {
id: number
name: string
data: T[]
class User<T> {
id: number;
data: T[];
constructor() {
this.id = 1;
this.data = [];
在实现react组件时,有时候我们也想通过泛型来定义某个属性的类型。比如常见的列表组件,如果不使用泛型,我们通常这样写:
//列表组件
interface Props {
list: any[], //因为我们并不知道传进来的数组类型,只能用any代替
renderItem: (item: any, i: number) => any
function MapList({ list = [], renderItem }) {
return (
{list.map(renderItem)}
</div>
interface ListVO {
id: number
name: string
amount: number
//存放列表组件的容器,即父组件
function TComponent = () => {
const list:ListVO[] = [
{ id: 1, name: "张一", amount: 1000 },
{ id: 2, name: "张二", amount: 2000 },
{ id: 3, name: "张三", amount: 3000 },
{ id: 4, name: "张四", amount: 4000 },
{ id: 5, name: "张五", amount: 5000 },
{ id: 6, name: "张六", amount: 6000 },
return (
<PageContainer title="泛型组件">
<MapList
list={list}
renderItem={(item) => (<p key={item.id}>{`${item.id}、${item.name}有¥${item.amount.toFixed(2)}`}</p>)}
</PageContainer>
当我们使用组件MapList的renderItem属性时就不会有任何ts提示和类型约束,这违背了我们使用ts的初心,要么在使用renderItem的时候每次都自己再定义一下renderItem={(item: ListVO) => (...)}
,比较麻烦,这时候泛型就派上大用场了,我们只需要在声明子组件的时候为list声明一个泛型,如下:
interface Props<T> {
list: T[],
renderItem: (item: T, i: number) => any
function MapList<T>({ list = [], renderItem }: Props<T>) {
return (
{list.map(renderItem)}
</div>
使用子组件,
<MapList<ListVO>
list={list}
renderItem={(item) => (...)}
当然,因为ts的泛型可以根据自己推导类型,我们可以不用手动传递类型,
<MapList
list={list}
renderItem={(item) => (...)}
看!这个时候ts的自动推导就实现啦~,你的组件可读性和维护性也提高一步咯~
如果你的组件是函数表达式,可以这样写,一样的,声明函数的不同泛型的写法有一丢丢不一样而已,
interface Props<T> {
list: T[],
renderItem: (item: T, i: number) => any
const MapList: <T>(props: Props<T>) => any = ({ list = [], renderItem }) => {
return (
{list.map(renderItem)}
</div>
闹个笑话自己笑
16.2k