I've been facing challenges when it comes to instantiating and initializing a model in TypeScript. In my project, I am using Nest where I receive an object from an API that needs to be validated by converting it to a DTO. This DTO should then be used to create an instance of the model.
The conventional approach would look something like this:
class MyModel {
public constructor(public property: string) {
}
}
class MyModelDto {
public property: string;
}
// Instantiation function, taking input from an HTTP POST body:
public function createMyModel(bodyData: MyModelDto) {
const myModel = new MyModel(bodyData.property);
}
The benefit of this method is that it ensures that a MyModel instance will never be created with incorrect properties, as they are all required and you cannot pass extra properties to the model. However, the drawback is having to include the full list of properties each time you instantiate your model. This is manageable with a few properties but becomes tedious when dealing with multiple (10+). Additionally, since the order matters, there is a risk of assigning data to the wrong property. As long as the types match, the compiler won't raise any errors.
An alternative approach could be:
class MyModel {
public property: string;
public constructor(data: MyModelInterface) {
Object.assign(this, data);
}
}
interface MyModelInterface {
property: string;
}
class MyModelDto {
public property: string;
}
// Instantiation function, taking input from an HTTP POST body:
public function createMyModel(bodyData: MyModelDto) {
const myModel = new MyModel(bodyData);
}
This method offers a cleaner way of instantiation. Even though you need to specify the same list of properties twice (in the model and interface), it never exceeds 2.
While this is preferable, the downside is that the compiler will only identify incorrect bodyData if you omit properties from the MyModelDto definition. It won't raise any issues if you add extra properties, and it won't exclude any data from your const myModel
. This diminishes many benefits of TypeScript.
It would be ideal if Object.assign
only accepted the properties specified in the MyModel
class, or if the MyModel interface flagged any differences between the input and the interface, not just missing properties. Unfortunately, JavaScript does not function in this manner.
I have explored other options (like creating my own version of Object.assign), but none seem to provide a clean solution. I find it somewhat surprising that such a fundamental issue lacks a straightforward resolution (though perhaps I am simply being naive).