Search code examples
typescripttypesconstructorconstructor-overloading

Type 'undefined' is not assignable to type 'number' within constructor definition


Issue

The parameter value maxORhealth prompts the following error; in VS Code:

Type 'undefined' is not assignable to type 'number'.ts(2345)

... and unsure how to navigate around this error.

Class Definition

    class Vitals implements IVitals
    {
        vitals!: 
        { 
            HealthValue:    number | undefined; 
            StrengthValue?: number | undefined;
            ManaValue?:     number | undefined; 
            StaminaValue?:  number | undefined; 
            IntelectValue?: number | undefined; 
            TuneValue?:     number | undefined; 
        };

        /// CONSTRUCTORS
        constructor()
        constructor(maxORhealth: number)
        constructor(maxORhealth: number, maxORstrength: number)
        constructor(maxORhealth: number, 
                    maxORstrength: number, 
                    mana: number, 
                    stamina: number, 
                    intelect: number, 
                    tune: number)
        constructor(maxORhealth?: number, 
                    maxORstrength?: number, 
                    mana?: number, 
                    stamina?: number, 
                    intelect?: number, 
                    tune?: number)
    {
           if (Number.isInteger(maxORhealth) && maxORstrength === undefined && mana === undefined)
           {
                this.vitals.HealthValue   = getRandomInt(maxORhealth);  <= Error .ts(2345)
                this.vitals.StrengthValue = getRandomInt(maxORhealth);
                this.vitals.ManaValue     = getRandomInt(maxORhealth); 
                this.vitals.StaminaValue  = getRandomInt(maxORhealth); 
                this.vitals.IntelectValue = getRandomInt(maxORhealth); 
                this.vitals.TuneValue     = getRandomInt(maxORhealth); 
           }
           else if (Number.isInteger(maxORhealth) && maxORstrength === undefined)
           {
                this.vitals.HealthValue   = maxORhealth; 
                this.vitals.StrengthValue = getRandomInt(maxORstrength!);
                this.vitals.ManaValue     = getRandomInt(maxORstrength!); 
                this.vitals.StaminaValue  = getRandomInt(maxORstrength!); 
                this.vitals.IntelectValue = getRandomInt(maxORstrength!); 
                this.vitals.TuneValue     = getRandomInt(maxORstrength!); 
            }
            else
            {
                this.vitals.HealthValue   = maxORhealth; 
                this.vitals.StrengthValue = maxORstrength;
                this.vitals.ManaValue     = mana; 
                this.vitals.StaminaValue  = stamina; 
                this.vitals.IntelectValue = intelect; 
                this.vitals.TuneValue     = tune; 
            }
        }
    }

Desired Affect

I would like to have three constructors for this class, as follows:

    constructor()
    constructor(maxORhealth: number)
    constructor(maxORhealth: number, maxORstrength: number)
    constructor(maxORhealth: number, maxORstrength: number, mana: number, stamina: number, intelect: number, tune: number)

... with (hopefully) a practical (none overly JS fancy) solution.

  • Cheers, and thanks in advance.

Solution

  • The error originates from this statement:

    Number.isInteger(maxORhealth)
    

    maxORhealth is of type number | undefined. Because it's an optional argument to the constructor, it can be either a number or undefined.

    Number.isInteger is typed to only accept a parameter of type number. Therefore TypeScript complains because maxORhealth could also be a number.


    To fix this you can do one of two things. You can introduce an additional check for undefined like this:

    if (maxORhealth !== undefined && Number.isInteger(maxORhealth) && maxORstrength === undefined && mana === undefined) {
    //  ^^^^^^^^^^^^^^^^^^^^^^^^^
    

    Playground

    Alternatively, considering Number.isInteger(undefined) is handled properly and just returns false, you could also convince TypeScript that it's okay anyway. To do that you can use the non-null assertion postfix ! operator:

    Number.isInteger(maxORhealth!)
    //                          ^
    

    This operator tells TypeScript that maxORhealth is not undefined and not null.

    Playground