As far as i know, typescript does not differentiate between prototype properties and instance properties. Also, there is no detection for Object.defineProperty
on the prototype, similar to a feature for typechecking js.
As such, is the "normal" way to make a prototype property to simply declare it, and define it outside the class, without TS being able to confirm this?
class C {
declare readonly x: string;
}
Object.defineProperty(
C.prototype,
'x',
{ value: 'something' },
);
In the specific case, i am extending Error
, and want to override Error.prototype.name
. This seems to be best done by in turn adding a prototype property on the subclass.
CodePudding user response:
I think the "normal" way is simply to use instance properties instead of prototype properties; or, put another way, there is no "normal" way to use prototype properties because they aren't very well supported and don't lead to idiomatic Typescript.
class A {
// instance property instead of prototype property
readonly x: string = 'foo';
}
If you are particularly concerned about memory use - perhaps you are going to have millions of instances of A
and you don't want them all to hold individual references to the same constant - then you can declare a property accessor using the get
keyword. This accessor belongs to the class, not the instances:
class B {
// behaves like a readonly property, but belongs to the prototype
get x(): string {
return 'foo';
}
}
// "foo"
console.log(new B().x);
// false
console.log(new B().hasOwnProperty('x'));
// true
console.log(B.prototype.hasOwnProperty('x'));
If you are also concerned about the theoretical minuscule performance cost of an accessor method compared to a simple property (this should be inlined by the JIT, but...), then the only reason Typescript won't allow you to assign C.prototype.x = ...;
directly is because you declared it as readonly
. That is, if Typescript is going to check the type of C.prototype.x
then it's also going to check that this property is writable. So you can get type-checking if you don't make x
readonly:
class C {
// not readonly, allowing direct assignment to the prototype
declare x: string;
}
// OK
C.prototype.x = 'foo';
// Error
C.prototype.x = { value: 'bar' };