如何让generateSelectOptions函数基于data参数自动推断field类型?
如何让React-Select选项生成函数自动推断字段键类型?
问题背景
我需要为react-select组件生成符合以下类型的选项数组:
type TOptions = { value: string; label: string }[]
数据源来自API,返回的数据结构示例如下:
type ApiDataItem = { name: string; slug: string; id: number; }
我已实现generateSelectOptions函数进行格式转换,但目前只能手动断言返回类型,且第二个参数的字段键无法自动推断为数据元素的键名,只能手动指定为string类型。希望优化类型定义,实现传入data后,field的valueKey和labelKey自动提示为data元素的合法键名。
解决方案
通过TypeScript泛型约束可以实现这一需求,同时还能额外做字段类型校验,确保映射后的value和label都是string类型。
基础自动推断版本
这个版本实现键名自动推断,同时保留基础的类型断言:
type TOptions = { value: string; label: string }[]; const generateSelectOptions = <T extends Record<string, unknown>>( data: T[], field: { valueKey: keyof T & string; labelKey: keyof T & string; } ): TOptions => { return data.map(item => ({ value: item[field.valueKey] as string, label: item[field.labelKey] as string, })); };
严格类型校验版本
如果需要确保选中的字段确实是string类型(避免误传number类型的字段如id),可以添加类型守卫做运行时和编译时的双重校验:
type TOptions = { value: string; label: string }[]; const generateSelectOptions = <T, V extends keyof T, L extends keyof T>( data: T[], field: { valueKey: V; labelKey: L; } ): TOptions => { // 类型守卫:校验选中字段是否为string类型 const isValidItem = (item: T): item is T & { [K in V | L]: string } => { return typeof item[field.valueKey] === 'string' && typeof item[field.labelKey] === 'string'; }; return data.map(item => { if (!isValidItem(item)) { throw new Error(`数据项 ${JSON.stringify(item)} 的指定字段不是字符串类型`); } return { value: item[field.valueKey], label: item[field.labelKey], }; }); };
使用示例
调用函数时,field的valueKey和labelKey会自动提示data元素的所有合法键名:
const data = [ { name: "Holy Holy Holy", slug: "holy-holy-holy", id: 1, }, { name: "Amazing Grace", slug: "amazing-grace", id: 2, }, ]; // 输入valueKey和labelKey时会自动补全name、slug、id const options = generateSelectOptions(data, { valueKey: "slug", labelKey: "name", }); // 转换后的结果: // [ // { label: "Holy Holy Holy", value: "holy-holy-holy" }, // { label: "Amazing Grace", value: "amazing-grace" } // ]
关键说明
- 泛型
T用于捕获输入data的具体类型,keyof T自动提取data元素的所有键名; - 严格版本的类型守卫确保只有字符串类型的字段能被映射为
TOptions的value和label,避免类型不匹配的问题; - 函数调用时,TypeScript会自动根据传入的
data推断field参数的合法键名,无需手动指定string类型。
内容的提问来源于stack exchange,提问作者Jerome Marshall
相关产品推荐
相关产品推荐

