Vishal
Vishal

Reputation: 445

How to detect correct type for a variable in Typescript when types are conditional

The code is like this:

class MyClass {
  getValue() {
    // some code here...
  }
}

const IS_ENABLED = process.env.IS_ENABLED || false;
const myClass = IS_ENABLED ? new MyClass() : null;

function getValue() {
  if (!IS_ENABLED) return false;

  return myClass.getValue();
}

Now at this point, TypeScript is giving error (for myClass.getValue()):

Object is possibly 'null'.

But, since I've checked the condition, I'm sure it's not null.

Is there any way for TypeScript to handle it?

Upvotes: 1

Views: 156

Answers (2)

Diamond
Diamond

Reputation: 3428

Type Guards allow you to narrow down the type of an object within a conditional block. You can use instanceof to make Typescript knows its type.

const IS_ENABLED = process.env.IS_ENABLED || false;
const myClass = IS_ENABLED ? new MyClass() : null;

function getValue() {
  if (!IS_ENABLED) return false;
  if (myClass instanceof MyClass) {
    return myClass.getValue();
  }
  return false;
}

For details please check this.

Upvotes: 0

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249536

Typescript will not keep track of variables that are related in this way. There are a number of patterns that act as type guards and change the type of a variable.

In this case since IS_ENABLED and myClass are very much related, you can just check the if myClass is undefined.

const IS_ENABLED = process.env.IS_ENABLED || false;
const myClass = IS_ENABLED ? new MyClass() : null;

function getValue() {
    if (!myClass) return false;

    return myClass.getValue();
}

Or you could use a discriminated union (this might be useful if you have multiple myClass type like varaibles):

const config = (process.env.IS_ENABLED || false) ? {
    IS_ENABLED: true as const,
    myClass: new MyClass(),
    myClass2: new MyClass()
} : {
    IS_ENABLED: false as const,
}

function getValue() {
    if (!config.IS_ENABLED) return false;
    config.myClass2.getValue();
    return config.myClass.getValue();
}

Upvotes: 2

Related Questions