[英]fixed-length array with optional items in Typescript interface
Angular使用FormBuilder类引入了模型驱动的表单,其主要方法group
具有如下签名:
group(controlsConfig: {
[key: string]: any;
}): FormGroup;
any
实际上是一个格式为的数组:
[
initial value of model's property,
sync validator(s),
async validator(s)
]
只需要第一个元素的地方。
我认为我想要一些比这更强类型的东西,特别是在与强类型模型相关的任何东西上,所以我用T来重新定义函数:
declare interface FormBuilder2 extends FormBuilder {
group<T>(controlsConfig: {
[K in keyof T]?: [T[K], ValidatorFn | ValidatorFn[] | null, ValidatorFn | ValidatorFn[] | null];
}): FormGroup;
}
这也意味着HTML中的所有formControlNames(当然还有group()调用中的所有)必须与我喜欢的模型属性相匹配。
它似乎工作,但一个snafu:
this.optionsForm = this.formBuilder2.group<CustomerModel>({
status: [this.model.status, [Validators.required], null],
lastOrder: [this.model.lastOrder, null, null],
comments: [this.model.comments, null, null],
});
我必须在未使用的阵列插槽上提供null
。
有没有办法让Typescript省略对无关null
的需要?
由于元组可以接受额外元素的方式,因此使用元组类型没有真正类型安全的方法。 也就是说,例如,元组类型[A, B, C]
实际上将接受类型A | B | C
其他元素 A | B | C
A | B | C
( 见文档 )。
但是,有一个解决方案! (见下面的尝试3)
(顺便说一句,你忽略了Angular对异步验证器的界面不同: AsyncValidatorFn
。)
尝试1:
[K in keyof T]?: [T[K] | ValidatorFn | ValidatorFn[] | null];
几乎没有any
打字(可能更糟,因为它看起来有误导性)。
尝试2:
[K in keyof T]?:
[T[K]] |
[T[K], ValidatorFn | ValidatorFn[]] |
[T[K], ValidatorFn | ValidatorFn[] | null, AsyncValidatorFn | AsyncValidatorFn[]];
乍一看似乎更好。 但问题是Typescript编译器只会抛出错误作为最后的手段。 所以它会接受这个:
someStringField: ['hi', 'hello']
因为这符合[T[K]]
(因为Typescript中的元组允许有额外的元素)。
尝试3:
有一个更好的解决方案,令我惊讶。 我在撰写这个答案的过程中发现了这一点,同时在Typescript GitHub repo上阅读了这个问题 。
[K in keyof T]?: {
0: T[K];
1?: ValidatorFn | ValidatorFn[];
2?: AsyncValidatorFn | AsyncValidatorFn[];
};
这是对先前尝试的改进,因为前三个元素总是被正确地进行类型检查。 ['hi', 'hello']
正确地给出了编译错误。 允许其他元素,可以是任何东西,按照通常的结构类型,但没关系。
希望这能解决你的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.