Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

360
Views
How to type constructor argument to initialise properties from plain object

I'm trying to come up with a simple way to write a class with a constructor that takes a plain object argument, and initialises the instance properties accordingly.

class Foo {
  x: string
  y: string

  constructor(init: Foo) {
    Object.assign(this, init)
  }
}


new Foo({x: 'a', y: 'b'})

This gives an error on the two properties: "has no initializer and is not definitely assigned in the constructor". If init is a valid Foo, which the type system says it is, those properties are definitely assigned in the constructor. I realise that assertion relies on an understanding of Object.assign, but I've seen other examples where it seems the compiler does have that.

What would be the best way to fix this? Right now I'm adding initialisers, but I'd prefer not to.

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

The compiler cannot perform the analysis on Object.assign(this, init) to know that all the properties of this will be initialized as a result. The typings for Object.assign(target, ...args) don't mutate the type of the target parameter at all.

You could use a definite assignment assertion for each and every property, to suppress the error:

class Foo {
  x!: string
  y!: string

  constructor(init: Foo) {
    Object.assign(this, init)
  }
}

and that's fine for a single Foo class with only two properties. But it could be quite tedious indeed if you have lots of properties to initialize.


In such cases, you could write a class factory function which generalizes the pattern of copying the constructor parameter into this. You only have to do a single type assertion inside the implementation:

function ClassFor<T extends object>() {
  return class {
    constructor(init: any) {
      Object.assign(this, init);
    }
  } as new (init: T) => T;
}

And then you can just use the factory to generate your specific class constructors:

class Foo extends ClassFor<{ x: string, y: string }>() {

}

And verify that it behaves as you like:

const foo = new Foo({ x: 'a', y: 'b' })    
console.log(foo.x.toUpperCase()) // "A"
console.log(foo.y.toUpperCase()) // "B"

Playground link to code

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!