Angular 12 自定义可复用表单组件设置Validator报类型错误如何解决?
Angular 12自定义表单组件设置validator类型错误排查
错误详情
Argument of type '(ValidatorFn | null | undefined)[]' is not assignable to parameter of type 'ValidatorFn | ValidatorFn[] | null'.
Type '(ValidatorFn | null | undefined)[]' is not assignable to type 'ValidatorFn[]'.
Type 'ValidatorFn | null | undefined' is not assignable to type 'ValidatorFn'.
Type 'undefined' is not assignable to type 'ValidatorFn'.
问题原因
这是TypeScript类型校验不匹配触发的错误,Angular表单的setValidators、setAsyncValidators方法仅允许传入ValidatorFn、ValidatorFn[]、null三类参数,你的代码中构造的校验器数组存在null/undefined类型的元素,不符合类型要求:
- 代码中使用
control?.validator可选链语法,当control为null时返回值为undefined - 即便
control存在,Angular内置的control.validator、control.asyncValidator本身类型定义就包含null - 你构造的
[control?.validator]数组元素类型为ValidatorFn | null | undefined,无法传入setValidators方法
解决方案
你可以通过提前判断空值、过滤空元素的方式修正代码,同时你原代码writeValue方法存在DOM赋值错误,也同步修正:
修正后完整代码
import { Component, ElementRef, Input, OnInit, Self, ViewChild } from '@angular/core'; import { ControlValueAccessor, NgControl, ValidatorFn, AsyncValidatorFn } from '@angular/forms'; @Component({ selector: 'app-text-input', templateUrl: './text-input.component.html', styleUrls: ['./text-input.component.css'] }) export class TextInputComponent implements OnInit, ControlValueAccessor { @ViewChild('input', { static: true }) input!: ElementRef; @Input() type = "text"; @Input() label!: string; constructor(@Self() public controlDir: NgControl) { this.controlDir.valueAccessor = this; } ngOnInit(): void { const control = this.controlDir.control; // 提前判空,避免后续空指针问题 if (!control) return; // 构造同步校验器数组,过滤空值 const validators = [this.controlDir.validator].filter(Boolean) as ValidatorFn[]; // 构造异步校验器数组,过滤空值 const asyncValidators = [this.controlDir.asyncValidator].filter(Boolean) as AsyncValidatorFn[]; control.setValidators(validators); control.setAsyncValidators(asyncValidators); control.updateValueAndValidity(); } onChange(event: Event) { } onTouched() { } writeValue(obj: any): void { // 修正原赋值错误,给input的value属性赋值,而非覆盖nativeElement本身 this.input.nativeElement.value = obj || ''; } registerOnChange(fn: any): void { this.onChange = fn; } registerOnTouched(fn: any): void { this.onTouched = fn; } }
内容的提问来源于stack exchange,提问作者Murat Kaya
相关产品推荐
相关产品推荐

