Angular Select组件如何根据multiple入参动态调整Output类型?
问题根源
原来的组件定义中,value和valueChange的类型为联合类型T | T[],TypeScript无法将该类型和multiple输入的布尔值做关联绑定,因此双向绑定时会认为值可能同时是单个值或数组,和外部绑定的变量类型冲突,触发类型报错。
可行实现方案
通过TypeScript条件类型+组件双泛型参数的方式,将multiple的取值和值类型进行绑定,无需拆分组件也无需关闭严格校验。
第一步:定义条件类型并改造组件泛型
// 条件类型:根据multiple的布尔值,动态返回对应的值类型 type SelectValueType<T, Multiple extends boolean> = Multiple extends true ? T[] : T; // 增加第二个泛型参数M,代表multiple的类型,默认值为false(默认非多选) export class SelectComponent<T, M extends boolean = false> implements OnInit { // 将multiple的类型绑定到泛型M @Input() multiple!: M; // value类型通过条件类型动态生成 @Input() value!: SelectValueType<T, M>; // 输出事件的类型也和条件类型绑定 @Output() valueChange = new EventEmitter<SelectValueType<T, M>>(); constructor() { } ngOnInit() { } // 可选:增加运行时类型校验兜底,避免传参不符合预期的情况 // private _value: SelectValueType<T, M>; // @Input() set value(v: SelectValueType<T, M>) { // if (this.multiple && !Array.isArray(v)) { // this._value = [v] as SelectValueType<T, M>; // return; // } // if (!this.multiple && Array.isArray(v)) { // this._value = v[0] ?? ('' as SelectValueType<T, M>); // return; // } // this._value = v; // } // get value() { // return this._value; // } }
第二步:正常使用组件即可
改造完成后,你原来的使用代码不会再触发类型报错,TypeScript会自动根据multiple的传入值推断对应的value类型:
<!-- 自动推断为非多选,value类型为string,和test变量匹配 --> <app-select [(value)]="test"></app-select> <!-- 自动推断为多选,value类型为string[],和test2变量匹配 --> <app-select [multiple]="true" [(value)]="test2"></app-select>
export class AppComponent { test = ""; test2: string[] = [] }
如果使用的Angular版本低于14,模板无法自动推断组件泛型,你也可以手动在模板中指定泛型参数即可:
<app-select [multiple]="true" [(value)]="test2" T="string" M="true"></app-select>
内容的提问来源于stack exchange,提问作者Crocsx
相关产品推荐
相关产品推荐

