Rocket interface:
interface Rocket {
name: string;
setName(name: string): void;
}
Rocket object - applies the rocket interface:
const rocket: Rocket = {
name: 'some-rocket',
setName: (name: string) => {
rocket.name = name
}
}
Now if I want to update the rocket name, I can do that like this:
rocket.setName('new-rocket-name')
But as you can see, the setName hardcoded inside the object itself. What if I want to put it in a seperate file? For example:
// set-rocket.ts
export const setRocket = (name: string) => {
// how to update the name of the object,
// which is not available in this scope?
}
I can change the interface and require to provide with the actual rocket object as a parameter, but it doesn't look that good:
interface Rocket {
name: string;
setName(rocket: Rocket, name: string): void;
}
And then set the rocket name like that:
rocket.setName(rocket, 'new-rocket-name')
Is there a better way doing it?
You can accomplish this by changing the Rocket interface to a class:
class Rocket {
constructor (public name: string) {}
setName(name: string) {
this.name = name;
}
}
const rocket = new Rocket('some-rocket');
console.log(`current rocket name: ${rocket.name}`);
rocket.setName('new-rocket-name');
console.log(`rocket name: ${rocket.name}`);
If you want to make the usage of Rocket more generic, i.e. you want to create different kinds of Rockets without relying too much on their implementation, we can dive deeper into OOP, and make use of a combination of interface (API) and class (Implementation).
interface Rocket {
readonly name: string;
}
interface ISetName {
setName: (name: string) => void;
}
class DynamicRocket implements Rocket, ISetName {
constructor(private _name: string) { }
setName(name: string) {
this._name = name;
}
get name() { return this._name };
}
The advantage of this second method is that you can have different implementations for the Rocket interface, while still maintaining the same API for changing their names. So elsewhere in your application, you may have:
const updateRocketName = (rocket: Rocket & ISetName, name: string) => {
rocket.setName(name);
return rocket.name;
}