Xavier Hamel
Xavier Hamel

Reputation: 574

In typescript, why isn't it possible to initialize a class property by calling a method?

The following typescript code works as expected but typescript throws a TS2564 error on the test2 and test3 properties. Is it because they are initialized inside of methods? How should a class like this be written.

I believe it works as expected because it is valid in javascript. Could it be caused by wrong typescript settings?

class class1{

    test1:number;//test1 is initialized as expected
    test2:number;//Property 'test2' has no initializer and is not definitely assigned in the constructor.
    test3:number;//Property 'test3' has no initializer and is not definitely assigned in the constructor.

    constructor(){
        //test1 
        this.test1 = 0;

        //test2
        const setTest2To0 = () =>{
            this.test2 = 0;
        };
        setTest2To0();

        //test3
        this.setTest3To0();
    }

    setTest3To0(){
        this.test3 = 0;
    }}

Upvotes: 6

Views: 3809

Answers (2)

Malvineous
Malvineous

Reputation: 27340

Since TypeScript 2.7 you can use the definite assignment assertion modifier which means adding an exclamation mark between the variable name and the colon:

test3!: number

This has the same effect as adding a // @ts-ignore TS2564 comment above it, and is you telling TS that you are definitely assigning it through all possible code execution paths through the constructor.

Upvotes: 4

TypeScript does not track this mutations in this case.

However, there is a workaround. You can use IIFE pattern for declaring test2 property.

class class1 {

    test1: number;//test1 is initialized as expected
    test2: number;// ok
    test3: number;//Property 'test3' has no initializer and is not definitely assigned in the constructor.

    constructor() {
        //test1 
        this.test1 = 0;

        //test2
        (() => {
            this.test2 = 0;
        })();

        //test3
        this.setTest3To0();
    }

    setTest3To0() {
        this.test3 = 0;
    }
}

As you might have noticed, TS is able to figure out that test2 is initialized in constructor.

Please keep in mind that typescript is about static validation.

So it is impossible to use setTest3To0 to initialize Test3?

Yes. You should use test3: number | undefined. Or you can use another syntax:


class class1 {
    static getTest3() {
        return 0
    }

    constructor(public test1 = 0, public test2 = 0, public test3 = class1.getTest3()) { }

}

If you use public keyword there is no need to declare all your properties as you did before. As you might have noticed I have used static method for setting test3 during class initialization.

Upvotes: 3

Related Questions