繁体   English   中英

固定长度数组,带有Typescript接口中的可选项

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM