实现接收字段数组与FormData的类型安全TS表单提取函数
实现数组参数的类型安全表单值提取函数
需求说明
需要编写一个TypeScript函数,接收两个参数:
- 字段配置数组:每个元素包含
name属性和可选type属性(type仅支持'number'或默认) - FormData对象
函数返回一个类型安全的对象:
- 键为字段的
name值 - 值的类型匹配字段
type:未指定则为string,指定'number'则转为number类型
预期效果:
const formData = new FormData(); formData.append('name', 'John Doe'); formData.append('age', '25'); const fields = [{ name: 'name' }, { name: 'age', type: 'number' }] as const; const data = extractFormValues(fields, formData); // 类型自动推断为 { name: string; age: number } // 运行值为 { name: 'John Doe', age: 25 }
解决方案
1. 定义基础类型
首先明确字段的类型约束,限制type只能是'number'或undefined:
type Field = { name: string; type?: 'number'; };
2. 实现类型安全的函数
通过泛型和映射类型,从数组元素中提取键和对应值的类型:
// 从字段数组类型T中提取最终返回的对象类型 type ExtractFormValues<T extends readonly Field[]> = { [K in T[number]['name']]: Extract<T[number], { name: K }>['type'] extends 'number' ? number : string; }; const extractFormValues = <T extends readonly Field[]>( fields: T, formData: FormData ): ExtractFormValues<T> => { const result = {} as ExtractFormValues<T>; for (const field of fields) { const value = formData.get(field.name); // 假设表单字段均有值,处理FormData.get可能返回null的情况 const rawValue = value as string; if (field.type === 'number') { result[field.name as keyof ExtractFormValues<T>] = Number(rawValue) as ExtractFormValues<T>[keyof ExtractFormValues<T>]; } else { result[field.name as keyof ExtractFormValues<T>] = rawValue as ExtractFormValues<T>[keyof ExtractFormValues<T>]; } } return result; };
3. 使用示例
注意需要给字段数组添加as const,让TypeScript推断出字面量类型,否则会丢失具体的name和type信息:
const fields = [{ name: 'name' }, { name: 'age', type: 'number' }] as const; const formData = new FormData(); formData.append('name', 'John Doe'); formData.append('age', '25'); const data = extractFormValues(fields, formData); // data的类型为 { name: string; age: number } console.log(data.name); // 类型提示为string console.log(data.age); // 类型提示为number
关键说明
- 泛型约束:
T extends readonly Field[]确保传入的数组元素符合Field类型,readonly允许使用as const的只读数组 - 映射类型
ExtractFormValues:遍历数组中所有元素的name作为键,通过Extract找到对应name的字段类型,判断其type来确定值的类型 as const的作用:强制TypeScript将数组元素的name和type推断为字面量类型(比如'name'而非string,'number'而非string),这样才能正确生成返回对象的类型
内容的提问来源于stack exchange,提问作者Anuja Nimesh
相关产品推荐
相关产品推荐

