TypeScript中React组件能否无需额外泛型实现动态查找类型?
实现方案:单泛型下动态匹配onClick参数类型
完全可以只通过单个泛型TData实现你要的效果,核心是利用TypeScript的映射类型把idField和onClick的参数类型做关联,让TypeScript自动根据传入的idField推断对应类型,不需要额外添加泛型参数。
具体代码实现
首先定义你的IPerson接口:
interface IPerson { age: number; name: string; }
然后修改组件的Props类型,通过映射类型生成联合类型,让idField和onClick的参数类型绑定:
import React from 'react'; type Props<TData> = { data: TData[]; } & { // 遍历TData的所有键,生成对应的idField和onClick组合 [K in keyof TData]: { idField: K; onClick: (id: TData[K]) => void; }; }[keyof TData]; // 取映射后的所有值类型,组成联合类型 function DataList<TData>(props: Props<TData>) { return ( <div> {props.data.map(item => ( <div key={item[props.idField]} onClick={() => props.onClick(item[props.idField])} > {JSON.stringify(item)} </div> ))} </div> ); }
使用示例
当你传入idField="age"时,TypeScript会自动约束onClick的参数为number类型:
// 正确:onClick的id是number类型 <DataList data={[{ age: 25, name: 'Alice' }, { age: 30, name: 'Bob' }]} idField="age" onClick={(id) => { console.log(id.toFixed(2)); // id是number,支持number的方法 }} />
当传入idField="name"时,参数自动变为string类型:
// 正确:onClick的id是string类型 <DataList data={[{ age: 25, name: 'Alice' }, { age: 30, name: 'Bob' }]} idField="name" onClick={(id) => { console.log(id.toUpperCase()); // id是string,支持string的方法 }} />
如果尝试传入不匹配的类型,TypeScript会直接报错:
// 错误:onClick的id应该是number,但传入了string类型的处理逻辑 <DataList data={[{ age: 25, name: 'Alice' }]} idField="age" onClick={(id) => { console.log(id.toUpperCase()); // 类型错误:number没有toUpperCase方法 }} />
原理说明
这里的关键是通过[K in keyof TData]遍历TData的所有键,为每个键生成一个包含idField: K和onClick: (id: TData[K]) => void的对象类型,然后通过[keyof TData]取所有这些对象类型组成联合类型。当你传入具体的idField值时,TypeScript会自动从联合类型中匹配对应的成员,从而约束onClick的参数类型。
内容的提问来源于stack exchange,提问作者r0n
相关产品推荐
相关产品推荐

