首页 > 解决方案 > 按名称调用 typeScript init 动态类 (2345)

问题描述

如何在不使用条件语句的情况下调用类?

问题:(参数)项目:输入“输入”类型的参数不能分配给“ISelect & IText”类型的参数。类型“ISelect”不可分配给类型“ISelect & IText”。“ISelect”类型中缺少属性“占位符”,但在“IText”类型中是必需的。(2345) input.ts(12, 5):此处声明了“占位符”。

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)

完整代码 typeScript 游乐场链接

标签: javascripttypescript

解决方案


因为它b是输入的联合,你需要在函数中再次缩小它map,不幸的是它是打字稿的限制。

let a = b.map(item =>
    item.type === 'inputSelect' ? new classes[item.type](item) : 
    item.type === 'inputText' ? new classes[item.type](item) : 
    undefined
);

或者您可以进行动态类型检查,那么您在inputs联合中的任何数量的接口上只需要 1 个条件。

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);

推荐阅读