Next.js Discord

Discord Forum

Least redundant ts class declaration

Unanswered
Sphecid wasp posted this in #help-forum
Open in Discord
Sphecid waspOP
What is best way to declare classes without multiplicating same keywords multiple times each?

What I tried:
- basic declaration with type: each property is repeated 4 times
- skip type: need to duplicate type declarations in class properties and in constructor
- Object.assign: could be best, but breaks types in instances
- factory: could be second best, but not available for methods

Example code. It can potentially have many fields, so writing each more than once is biggest obstacle.
Perfect solution would be Object.assign, if it worked with types properly

type EntityType = {
    name?: string | null
}

class Entity implements EntityType {
    name

    constructor(input: EntityType) {
        this.name = input.name
    }

    hello() {
        console.log('hello', this.name)
    }
}

6 Replies

Longtail tuna
why not inheritance?

class BaseEntity {
  private name: string;

  public constructor(name: string) {
    this.name = name;
  }

  public hello(): void {
    console.log("hello", this.name);
  }
}

class Entity extends BaseEntity {
  public constructor(name: string) {
    super(name);
  }
}

const entity = new Entity("...");
entity.hello();
also to ensure BaseEntity can't be instantiated you can make it abstract
To reduce redundancy in class declarations in TypeScript, the cleanest and most type-safe solution is to declare constructor parameters with public or private modifiers:

class Entity {
constructor(public name?: string | null) {}

hello() {
console.log('hello', this.name)
}
}


This gives you:

Field declaration ✅

Constructor assignment ✅

Type annotation ✅
...all in one line, with no need for implements or manual assignments.

If you want to reuse an external type like EntityType, but avoid boilerplate:

type EntityType = {
name?: string | null
}

class Entity {
name?: string | null

constructor(input: EntityType) {
Object.assign(this, input)
}

hello() {
console.log('hello', this.name)
}
}


This keeps things DRY and uses Object.assign safely — but keep in mind that it sacrifices strict property checks and might allow extra keys without error.
What is best way to declare classes without multiplicating same keywords multiple times each?

personal thought:

its going to be a tough road if you want to follow this principle in TS.

while TS is quite advanced at inferring types and really improve DX for developers, trying to minimise duplication is still hard to do and not really worth perfecting over in my opinion.

---

type EntityType = {
    name?: string | null
}

class Entity implements EntityType {
    name

    constructor(input: EntityType) {
        this.name = input.name
    }

    hello() {
        console.log('hello', this.name)
    }
}


The goal that you are supposed to aim is to have an error that cascades properly when one thing is changed. Sure you might want to type multiple times 2-3 times but at the very least the errors are visible and no hidden errors appears when you need to change something.
@Sphecid wasp It works. Although inherited class requires to still declare properties and their types twice. Which is extra work for same result
inherited class doesn't need to have its properties declared twice. as seen in ngr's code, you dont need to redeclare name though..