Reputation: 1350
Need to assign porperties to the only defined from the interface if used with spread operator.
I am expecting a solution for using typescript constructor with spread operator.
For eg.
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;
}
}
this is one option so the moment when I call this class like this, no way how many members are there but I would be having only id, name
to final object.
new Brand({...data })
Case: But when I have 25+ keys to the 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);
}
}
I am expecting not to write all properties again constructor. No matter it has 25 it would be just assigning that existing properties would be assigned. If data has section, genre
or any other property it would be ignored.
My 2nd snippet doesn't work.
Upvotes: 10
Views: 12309
Reputation: 2637
If you are willing to forego inheritance and encapsulation and embrace composition instead, then you can use types instead of classes and interfaces. IMHO this is where TypeScript really shines.
I am going to use a slightly different scenario than your Brand
example, because I think it demonstrates the power of TypeScript better.
Lets start by defining two types:
type Person = {
id: string
name: string
}
type Editable = {
canEdit: boolean
save(): Promise<boolean>
}
I can compose these into a new type:
type EditablePerson = Editable & Person
This allows me to construct a new person like this:
const person: Person = { id: '12345', name: 'Martin' }
then use this person
to construct an EditablePerson
like this
const editablePerson: EditablePerson = {
...person,
canEdit: true,
save: () => {
console.log(this.name)
return Promise.resolve(true)
}
}
I can also write an EditablePerson
constructor function that uses the spread operator like this:
const EditablePerson = function(editable: Editable, person: Person): EditablePerson {
return { ...editable, ...person }
}
Which allows me to construct an EditablePerson
like this:
editablePerson = EditablePerson(
{ canEdit: true, save:() => Promise.resolve(true) },
person)
Using the structured typing system in TypeScript brings you much closer to JavaScript and is less like writing in other OOP languages. I really love this style of writing TypeScript because I have long been an opponent of inheritance and always preferred composition.
Using this approach, your Brand example might look something like:
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!' })
Upvotes: -1
Reputation: 7826
This doesn't use the spread operator, but you could use the method from this answer
constructor(data: IBrand) {
for (let key in data) {
this[key] = data[key];
}
}
then instantiate...
new Brand(data);
Upvotes: 9
Reputation: 1350
I find a better solution for recurring code using class-transformer package. It also helps to expose and transform input into the required output.
Upvotes: 6