Home > Mobile >  Is there a better shorthand for Typescript class/interface definitions?
Is there a better shorthand for Typescript class/interface definitions?

Time:10-22

I'm defining a typescript class with constructor parameters defined by an interface, and it restricts the properties to only those that are defined.

The following code snippet works as intended, however, is there a way to reduce the code so that it isn't so repetitive? Each property is mentioned 4 times, there must be a better way.

interface MyInterface {
  property1: string;
  property2: boolean;
  property3: number;
}
class MyClass {
  property1: string;
  property2: boolean;
  property3: number;
  constructor(parameters: MyInterface) {
    this.property1 = parameters.property1;
    this.property2 = parameters.property2;
    this.property3 = parameters.property3;
  }
}

const example = new MyClass({property1: "Property 1", property2: true, property3: 3, extraProperty: "Shouldn't exist"});
console.log(example);

EDIT: I also need to restrict the properties at run-time from objects with additional unknown properties.

CodePudding user response:

How's this?

interface MyInterface {
    property1: string;
    property2: boolean;
    property3: number;
}

class MyClass implements MyInterface {
    property1: string;
    property2: boolean;
    property3: number;

    constructor(parameters: MyInterface) {
        Object.assign(this, parameters);
    }
}

CodePudding user response:

I believe this would be the most concise way, but not necessarily the best. It depends on your use case—specifically whether or not the parameters in the constructor will always match the declared properties of your class. If not, then you would want to stick with using an interface (and using an interface might be cleaner anyway).

class MyClass {
    property1!: string
    property2!: boolean
    property3!: number

    constructor(parameters: typeof MyClass.prototype) {
        Object.assign(this, parameters)
    }
}

CodePudding user response:

interface MyInterface {
  property1: string;
  property2: boolean;
  property3: number;
}

class MyClass implements MyInterface {
  constructor(
    public property1: string,
    public property2: boolean,
    public property3: number
  ) { }
}

const example = new MyClass("Property 1", true, 3, "Shouldn't exist");
console.log(example);

By putting public in the constructor arguments, I don't need to declare them outside of the constructor. MyClass implements MyInterface so that I know I have declared all properties I need in MyClass.

Maybe this doesn't really apply to your needs since you'll have to manually assign each property in the constructor, but it might give you something to think about.

CodePudding user response:

Yes, it is possible, but then you need to story class argument in parameters property:

interface MyInterface {
  property1: string;
  property2: boolean;
  property3: number;
}
class MyClass {
  constructor(public parameters: MyInterface) {  }
}

const example = new MyClass({ property1: "Property 1", property2: true, property3: 3, extraProperty: "Shouldn't exist" });
console.log(example);

example.parameters.property1 // ok

enter image description here

If you want to validate your object in runtime, you should either use user-defined-type-guards or io-ts

TypeScript has static type system

  • Related