Home > database >  Create prototype property
Create prototype property

Time:12-15

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' };

Playground Link

  • Related