TypeScript类型定义中能否为TypedFormGroup添加类型检查断言
实现方案
完全可以实现,你需要借助TypeScript的条件类型来区分T属性的类型,分别映射为普通控件和嵌套的TypedFormGroup即可。
核心优化逻辑
你写的类型断言思路是对的,只要把运行时判断T[key] is string替换为TS静态类型判断的条件类型即可,改进后的完整代码如下:
// 条件类型:根据属性类型映射对应的控件类型 type ControlMapType<T> = // 如果是对象类型(排除数组)则映射为嵌套TypedFormGroup T extends object ? T extends Array<any> ? AbstractControl : TypedFormGroup<T> // 基础类型映射为普通AbstractControl,你也可以改成FormControl<T>实现值类型推导 : AbstractControl; export class TypedFormGroup<T> extends FormGroup { // 替换原来的controls类型定义 override controls!: { [key in keyof T]: ControlMapType<T[key]> }; constructor(controls: { [key in keyof T]: ControlMapType<T[key]> }) { super(controls); } // 可选:覆盖get方法,让通过get取控件也能拿到正确类型 override get<K extends keyof T>(key: K): ControlMapType<T[K]> | null { return super.get(key as string) as ControlMapType<T[K]> | null; } }
使用示例
// 定义表单结构类型 interface OrderForm { orderId: string; totalAmount: number; receiverInfo: { name: string; phone: string; address: string; }; } // 初始化表单 const orderForm = new TypedFormGroup<OrderForm>({ orderId: new FormControl(''), totalAmount: new FormControl(0), // 嵌套子表单必须用TypedFormGroup初始化,才能匹配类型 receiverInfo: new TypedFormGroup({ name: new FormControl(''), phone: new FormControl(''), address: new FormControl('') }) });
效果验证
- 访问
orderForm.controls.receiverInfo时,TS会自动识别为TypedFormGroup<{name: string; phone: string; address: string}>类型,可直接点出receiverInfo.controls.name等嵌套控件,IntelliSense提示完全正常。 - 访问
orderForm.controls.orderId时,识别为普通AbstractControl,如果你需要推导FormControl的value类型,把ControlMapType的基础类型分支改成FormControl<T>即可。
注意事项
如果你的TS版本低于4.3或者Angular版本低于14,去掉代码里的override关键字即可正常使用。如果需要支持FormArray类型,只需在ControlMapType里新增数组类型的分支,映射为你自定义的TypedFormArray类型即可。
内容的提问来源于stack exchange,提问作者lukasz iwaszkiewicz
相关产品推荐
相关产品推荐

