Home > Software engineering >  Sealing a class doesn't work by decorator on the class
Sealing a class doesn't work by decorator on the class

Time:05-18

I'm trying to use decorator to seal my class object nevertheless sounds it's does not work. after initialization of the class i could delete a property or add another one to the class, you could see the code here:

function sealed(constructor: Function) {
  Object.seal(constructor);
  Object.seal(constructor.prototype);
}

@sealed
class BugReport {
  type = 'report';
  title: string;

  constructor(t: string) {
    this.title = t;
  }
}

const bug = new BugReport('but');

delete bug.title;
delete bug.type;

console.log(bug); // BugReport {}

but i have tried to seal a pure object and everything works fine. see this code:

const obj = {
  name: 'Jack',
};

Object.seal(obj);

delete obj.name;

console.log(obj); // will throw an error: Cannot delete property 'name'

tsconfig.json file

{
  "compilerOptions": {
    // `target` and `lib` match @tsconfig/bases for node12, since that's the oldest node LTS, so it's the oldest node we support
    "target": "es2019",
    "lib": ["es2019", "es2020.promise", "es2020.bigint", "es2020.string", "dom"],
    "rootDir": "src",
    "outDir": "dist",
    "module": "commonjs",
    "moduleResolution": "node",
    "strict": true,
    "declaration": true,
    "sourceMap": true,
    "inlineSources": true,
    "types": ["node"],
    "stripInternal": true,
    "incremental": true,
    "skipLibCheck": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "strictPropertyInitialization": false
  },
  "ts-node": {
    "swc": true
  },
  "include": ["src/**/*"],
  "typedocOptions": {
    "entryPoints": ["./src/index.ts"],
    "readme": "none",
    "out": "website/static/api",
    "excludeTags": ["allof"],
    "categorizeByGroup": false,
    "categoryOrder": ["Basic", "REPL", "Transpiler", "ESM Loader", "Other"],
    "defaultCategory": "Other"
  }
}

so why the decorator function could not manipulate the class at all ?!

thanks for any helps.

CodePudding user response:

Object.seal as described by the MDN page:

The Object.seal() method seals an object, preventing new properties from being added to it and marking all existing properties as non-configurable.

You are sealing the class constructor itself, and its prototype.

Notice that when you do this:

BugReport.prototype.modified = 42;

You will get an error because the prototype is sealed. Similarly, trying to modify the constructor will also result in an error:

BugReport.modified = 42;

And also notice that the properties on the class aren't on the prototype, too:

console.log(BugReport.prototype); // {}

To achieve the desired behavior you want, you need to seal it in the class constructor:

constructor(t: string) {
    this.title = t;

    Object.seal(this); // seal THIS instance
}

And now when you attempt to modify the instance you get errors.

Try this out in the playground.

CodePudding user response:

You can start by seeing what console.log(BugReport) outputs

  • Related