A common structure I use in TS is taking a plain JSON object definition and turning it into a class at runtime. For example:
export type LessonDef = {
id: string
title: string
slug: string
shortdesc: string
explanation: string
exercises: {
from: string
message: string
translation: string
hint?: string
feedback?: { [key: string]: string }
}[]
}
export class Lesson {
constructor(readonly def: LessonDef) {
Object.assign(this, def)
}
// Additional methods go here
}
The problem is that the type system doesn’t understand the result of the Object.assign. How can I tell TypeScript that Lesson extends the type of LessonDef?
>Solution :
Please see related answer
You can merge your class declaration and interface.
Consider this example:
interface Lesson {
id: string
title: string
slug: string
shortdesc: string
explanation: string
exercises: {
from: string
message: string
translation: string
hint?: string
feedback?: { [key: string]: string }
}[]
}
declare let x: Lesson;
class Lesson {
constructor(def: Lesson) {
Object.assign(this, { ...def });
}
}
const result = new Lesson(x)
result.exercises // ok
I have used {...def} instead def to avoid creating of extra def property in this
However, there is a drawback, you can refer to this.exercises before Object.assign
class Lesson {
constructor(def: Lesson) {
this.exercises //ok, <----- DRAWBACK!
Object.assign(this, { ...def });
}
}