具有扩展运算符的Typescript构造函数

xu3bshqb  于 2023-06-07  发布在  TypeScript
关注(0)|答案(3)|浏览(217)

如果与扩展操作符一起使用,则需要将属性分配给从接口定义的唯一。
我期待一个解决方案,使用类型脚本构造函数与传播运算符。
对于例如。

export interface IBrand {
    id: string;
    name: string;
}

export class Brand implements IBrand {
    id: string;
    name: string;       

    constructor(data: IBrand) {
        this.id = data.id;
        this.name = data.name;
    }
}

这是一个选项,所以当我这样调用这个类的时候,不知道有多少成员,但我只会有id, name到最终对象。

new Brand({...data })

案例:但是当我有25+键到data

export interface IBrand {
    id: string;
    name: string;
}

export class Brand implements IBrand {
    id: string;
    name: string;       

    constructor(data: Partial<IBrand>) {
        Object.assign(this, data);
    }
}

我希望不要再次编写所有属性的构造函数。不管它有25,它只是分配现有的属性。如果数据具有section, genre或任何其他属性,则将忽略它。
我的第二个片段不工作。

p5fdfcr1

p5fdfcr11#

这不使用spread运算符,但可以使用this answer中的方法

constructor(data: IBrand) {
    for (let key in data) {
        this[key] = data[key];
    }
}

然后示例化

new Brand(data);
sqyvllje

sqyvllje2#

我找到了一个更好的解决方案,使用class-transformer包重复代码。它还有助于将输入公开和转换为所需的输出。

tzdcorbm

tzdcorbm3#

如果您愿意放弃继承和封装,转而采用组合,那么您可以使用类型而不是类和接口。恕我直言,这是TypeScript真正闪耀的地方。
我将使用一个与Brand示例略有不同的场景,因为我认为它更好地展示了TypeScript的强大功能。
让我们从定义两种类型开始:

type Person = {
    id: string
    name: string
}

type Editable = {
    canEdit: boolean
    save(): Promise<boolean>
}

我可以把它们组合成一个新的类型:

type EditablePerson = Editable & Person

这让我可以这样构建一个新的人:

const person: Person = { id: '12345', name: 'Martin' }

然后用这个person构造一个EditablePerson,如下所示

const editablePerson: EditablePerson = {
    ...person,
    canEdit: true,
    save: () => {
        console.log(this.name)
        return Promise.resolve(true)
    }
}

我还可以编写一个EditablePerson构造函数,它使用spread运算符,如下所示:

const EditablePerson = function(editable: Editable, person: Person): EditablePerson {
    return { ...editable, ...person }
}

这允许我像这样构造一个EditablePerson

editablePerson = EditablePerson(
    { canEdit: true, save:() => Promise.resolve(true) }, 
    person)

在TypeScript中使用结构化类型系统可以让你更接近JavaScript,并且不像用其他OOP语言编写。我真的很喜欢这种TypeScript的写作风格,因为我一直反对继承,一直更喜欢复合。
使用这种方法,您的品牌示例可能如下所示:

type IBrand {
    id: string
    name: string
}

type Brand = {
    brandField?: string
    brandMethod: () => string
} & IBrand

const Brand = function(brand: IBrand): Brand {
    return { ...brand, brandMethod: () => 'Hello from Brand' }
}

const myBrand: IBrand = Brand({ id: 'abc', name: 'Wonderful Products!' })

相关问题