Reputation: 7589
I have a selector component.
The selector take a value that can be either a string/number etc... or an array of string/number etc..
https://stackblitz.com/edit/angular-ivy-gjbpvw?file=src/app/app.component.html
export class SelectComponent<T> implements OnInit {
@Input() value: T | T[]
@Input() multiple: boolean;
@Output() valueChange = new EventEmitter<T | T[]>()
constructor() { }
ngOnInit() {
}
}
I would like to use all strict check types, but I face a problem with this input.
<app-select [(value)]="test"></app-select>
<app-select [multiple]="true" [(value)]="test2"></app-select>
export class AppComponent {
test = "";
test2: string[] = []
}
The above will complain about
type 'string | string[]' is not assignable to type 'string'.
I wonder if there is a way without remove the strict check and without making 2 components, to change the Output value based on multiple
If multiple = true
output will always be an array
If multiple = false
output will never be an array
Is there a way ?
Upvotes: 1
Views: 865
Reputation: 170
I tried one thing and it seems to work :
select.component.ts
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'app-select',
templateUrl: './select.component.html',
styleUrls: ['./select.component.css']
})
export class SelectComponent<T, U extends boolean, V = U extends true ? T extends any[] ? T : T[] : T extends (infer Tt)[] ? Tt : T> implements OnInit {
@Input() value: V;
@Input() multiple: U;
@Output() valueChange = new EventEmitter<V>();
constructor() {}
ngOnInit() {}
}
So I had the type U
and V
in your component. U
is only a boolean and type the input multiple
.
V
check if U
is true
. If yes check if T
is an array as it should be. If it's the case, V
is equal to T
else V
is equal to T[]
. If U
is false
, check if T
is an array. If true so get the type of element without the array and assign it to V
, else V
= T
.
Upvotes: 2
Reputation: 32629
The Angular complaint is justified :) - but you should realize that it is complaining about the output not the input to the component.
It is complaining that the EventEmitter<T | T[]>
can emit a type that is incompatible with the type of the input variable.
If you change the declaration of test
and test2
to the following, it will work:
test: string | string[] = "";
test2: string | string[] = [];
Upvotes: 1