5

I'm trying to have a constructor on my class where I don't need to manually type out every field like so:

this.x = data.x;
this.y = data.y;

Instead I'd like to assign all fields at once from a single object. I found examples online that suggested the following method:


export class GameState {
    x: number;
    y: number;
 
    constructor(fields: GameState) {
        Object.assign(this, fields);
    }
}

However my code won't compile. I'm getting the following error:

Property 'x' has no initializer and is not definitely assigned in the constructor.
Property 'y' has no initializer and is not definitely assigned in the constructor.

Is this a viable approach and if so what am I missing?

If not, what's a better approach?

3

3 Answers 3

4

Object.assign() should work like you want, setting all the member variables from the constructor argument. Since the compiler can't tell that the member variables will be assigned by Object.assign(), use a non-null assertion operator with the member properties.

The non-null assertion operator exists for this very reason - to tell the type-checker that those values won't be null when it can't make the determination.

class GameState {
    x!: number;
    y!: number;
 
    constructor(fields: GameState) {
        Object.assign(this, fields);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Technically this is a "defnite assignment" assertion operator. see stackoverflow.com/a/67303411/567493
2

The error looks ambiguous, but typescript is just telling you that x and y may not be defined after one constructs a GameState object.

There are two ways to solve this:

  • Make x and y optional

    export class GameState {
      x?: number;
      y?: number;
    
      constructor(fields: GameState) {
        Object.assign(this, fields);
      }
    }
    
  • Assign x and y default values

    export class GameState {
      x: number = NaN;
      y: number = NaN;
    
      constructor(fields: GameState) {
        Object.assign(this, fields);
      }
    }
    

A third option exists, and I usually use this when I write classes in Typescript:

export class GameState {
    constructor(public x: number = NaN, public y: number = NaN) {}
}

There! Now x and y can be directly assigned a value from the constructor

Comments

1

I guess you are using latest version of typescript, and it is strict checking your variables, as x & y are not being initialized anywhere it is throwing errors. There can be 3 ways to fix your problem

  1. Strict Property Initialization -> Go to tsconfig.json and add "strictPropertyInitialization": false. This will prevent such errors.
  2. Initialize x & y or all such variables or use Definite Assignment Assertion to tell typescript that these variables wont be run at runtime.
  3. If you are using vscode, change version of ts.

your code is working fine with me Stackblitz

3 Comments

if you go to TS Config dropdown on top. Under the Type Checking settings uncheck strictPropertyInitialization checkbox. The errors will be gone.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.