Reputation: 1801
does js/ts has something like impl in Rust or extension in Swift? this is a good pratice to implement method for object with a specific shape. and we can replace userSetAge(user, x => x + 1)
to user.setAge(x => x + 1)
. Not only that, it can still work after spread copyed object.
here is an example in React data fetching and render it:
interface User {
name: string;
age: number;
setAge(fn: (age: number) => number): User;
}
impl User {
setAge(self, fn) {
self.age = fn(self.age);
return this;
}
}
// it works
const eczn: User = { name: 'eczn', age: 17 };
({ ...eczn }).setAge(x => x + 1);
import useSWR, { mutate } from 'swr';
// React App
function UserCard(props: { user: User }) {
return (
<div onClick={() => {
mutate(
`/api/user/${props.user.name}`,
props.user.setAge(x => x + 1)
);
}}>
Current Age: { props.user.age }
</div>
)
}
function App() {
const { data, loading } = useSWR<User>('/api/user/eczn')
if (loading) return <div>loading ...</div>
return <UserCard user={{ ...data }} />
}
a bad implementation :: Object.prototype.setAge
Object.prototype.setAge = function(fn) {
this.age = fn(this.age);
}
const eczn: User = { name: 'eczn', age: 17 };
({ ...eczn }).setAge(x => x + 1);
obviously, it is a bad practice.
Upvotes: 0
Views: 579
Reputation: 12055
If you use Javascript/Typescript classes, then you can override methods of the base class simply by declaring them on the child. The JS interpreter looks on the object for any method you call, and if it does not find it there, it looks on the prototype. You declare a child class using the extends
keyword. See https://javascript.info/class-inheritance for more information.
In the above case, you use an interface rather than a class for User. An interface is just a compile-time construct in Typescript for type checking purposes, so you cannot implement anything on it, and Typescript has vanished from the scene at runtime so it can't help you then.
If you made User into a class, then you could of course define the setAge method on it, and derive from it and then call setAge on that. You could even use the spread operator and keep the function so long as you aren't going to be calling methods on the prototype, which are not copied over.
In short, there's no equivalent of Rust's impl
, and that's because JS is object-oriented and Rust is not. Rust is based on the idea of composition rather than inheritance. So in JS, you have to use the object oriented approach available to you.
Upvotes: 3