problem: (parameter) item: inputs Argument of type 'inputs' is not assignable to parameter of type 'ISelect & IText'. Type 'ISelect' is not assignable to type 'ISelect & IText'. Property 'placeholder' is missing in type 'ISelect' but required in type 'IText'.(2345) input.ts(12, 5): 'placeholder' is declared here.
interface IInput {
id: number
title: string
}
interface ISelect extends IInput {
type: "inputSelect",
value: string
selects: string[]
}
interface IText extends IInput{
type: "inputText",
placeholder: string
value: string
}
type inputs = ISelect | IText
class InputSelect implements ISelect {
public id: number
public title: string
public value: string
public selects: string[]
public type: ISelect['type'] = "inputSelect"
constructor(
inputs: ISelect
) {
this.id = inputs.id
this.title = inputs.title
this.value = inputs.value
this.selects = inputs.selects
}
setValue(value: string) {
this.value = value
}
}
class InputText implements IText {
public id: number
public title: string
public value: string
public placeholder: string
public type: IText['type'] = "inputText"
constructor(
inputs: IText
) {
this.id = inputs.id
this.title = inputs.title
this.value = inputs.value
this.placeholder = inputs.placeholder
}
setValue(value: string) {
this.value = value
}
}
let b: inputs[] = [
{
id: 1,
title: "some select",
value: "",
selects: ["Moskow", "Bejing"],
type: "inputSelect"
},
{
id: 2,
title: "some text input",
value: "",
placeholder: "yourName",
type: "inputText"
}
]
const classes = {
inputText: InputText,
inputSelect: InputSelect
}
let a = b.map(item => new classes[item.type](item)) \\here error
console.log(a)
full code typeScript playground link
because the b
is a union of inputs you need to narrow it again in the map
function, unfortunately it's a limitation of typescript.
let a = b.map(item =>
item.type === 'inputSelect' ? new classes[item.type](item) :
item.type === 'inputText' ? new classes[item.type](item) :
undefined
);
or you can do a dynamic type check, then you need only 1 condition on any amount of interfaces in the inputs
union.
const checker = <T extends inputs>(item: T, cl: unknown): cl is ({new (a: T): InstanceType<(typeof classes)[T['type']]>}) => {
return classes[item.type] === cl;
};
let a = b.map(item => {
const cl = classes[item.type];
return checker(item, cl) ? new cl(item) : undefined;
}).filter((v): v is NonNullable<typeof v> => !!v);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.