如何编写泛型类型,用FormGroup/FormArray包装TypeScript接口属性?
修正Angular表单泛型类型实现
你的泛型类型错误在于判断逻辑——K extends []是在判断属性名是否为数组,这显然不成立(属性名是字符串,比如phones),正确的做法是判断属性值的类型是否为数组,再分支处理不同的表单控件类型。
步骤1:定义辅助类型
先创建几个辅助类型,用来识别数组、对象类型,以及提取数组元素类型:
// 提取数组的元素类型 type ArrayElement<T> = T extends (infer U)[] ? U : never; // 判断是否为数组类型 type IsArray<T> = T extends any[] ? true : false; // 判断是否为非数组的对象类型 type IsObject<T> = T extends object ? T extends any[] ? false : true : false;
步骤2:修正GenericFormModel泛型
结合Angular的表单控件类型,重新编写泛型:
import { FormControl, FormGroup, FormArray } from '@angular/forms'; export type GenericFormModel<T> = { [K in keyof T]: IsArray<T[K]> extends true ? FormArray<GenericFormModel<ArrayElement<T[K]>>> : IsObject<T[K]> extends true ? FormGroup<GenericFormModel<T[K]>> : FormControl<T[K] | null>; };
类型验证
假设Phone接口定义如下:
interface Phone { number: string; type: string; }
此时GenericFormModel<Person>会被推导为:
{ name: FormControl<string | null>; age: FormControl<number | null>; phones: FormArray<FormGroup<{ number: FormControl<string | null>; type: FormControl<string | null>; }>>; }
完全符合需求:数组属性phones对应FormArray,非数组的基本类型属性对应FormControl,如果是对象类型的属性则对应FormGroup。
内容的提问来源于stack exchange,提问作者matthew
相关产品推荐
相关产品推荐

