Issue
I'm using this (complexity super reduced) base model in Typescript:
export class ModelBase<T> {
constructor(base: T) {
Object.assign(this, base);
}
}
If I now try to use it as follows:
interface Model {
prop: string;
}
class MyClass {
constructor() {
let instance = new ModelBase<Model>({ prop: 'test' });
instance.prop = 'x';
}
}
Typescript tells me there is no property prop in my instance. How to get rid of it?
Solution
microsoft/TypeScript#2225, originally filed in 2015, requests similar cases where a class or interface extends a generic type. The discussion was closed, though some commenters seem to maintain at the end that the type intersection recommendations do not meet their needs.
As such, one way to do this is to make a static factory method that returns a type intersection of ModelBase<T> & T:
export class ModelBase<T> {
static wrap<T>(base: T) {
return new ModelBase<T>(base) as ModelBase<T> & T;
}
constructor(base: T) {
Object.assign(this, base);
}
}
Naturally, the function could easily be top-level or adjacent to the class rather than within it Java-style. Also, bear in mind that like with everything TypeScript you'll have an imprecise reflection of which properties are enumerable own properties (see #9726), which might be a signficantly narrower set than what you and TypeScript would expect to be available on ModelBase<Foo>. Conversely, you may copy more at runtime than TS can expect at compile-time, and ModelBase instances may have their methods and fields hidden if you have name collisions between ModelBase and whichever T types you're copying: TypeScript will only show you the inferred compile-time interactions rather than any unexpected enumerable runtime properties that Object.assign will copy for you.
Alternatives that don't work:
ModelBase<T> extends T, see #4890 which led to mixins belowModelBase<T> implements T, see #2225 linked above- constructor returns
ModelBase<T> & T, see #27594 - mixins, see #13743: Mixins necessarily accept constructor functions, not instances with interface types
Answered By - Jeff Bowman
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.