0

I want to create function that checks if variable is not null or undefined.

What I want is to safe type of variable after the check.

In my last project I did it following:

function isDefined<T>(value: T): value is T {
  return <T>value !== undefined && <T>value !== null;
}

But somewhy it doesn't work in my current project, perhaps due to different tsconfig - I can see a number of errors like "variable might be null" after isDefined(foo) (projects are use same typescript versions - "2.7.2")

I also saw another approach, which is works, but... a bit weird in terms or types.

function isDefined(value: any): value is {} | string | number | boolean {
  return value !== undefined && value !== null;
}

Question: How to create isDefined that would save type of the variable?


UPD1: Example of usage:

const foo: string | undefined = 'foo';

function getFoo(foo: String): void { 
  console.log(foo);
}

function getBar(foo: string | undefined) {
  if (isDefined(foo)) {
    getFoo(foo); // getFoo still think that foo maight be undefined
  }
}

export function isDefined<T>(value: T): value is T {
  return <T>value !== undefined && <T>value !== null;
}
S Panfilov
  • 16,641
  • 17
  • 74
  • 96

2 Answers2

1

I know this post is a little bit old, but now i think you can simply write something like

/**
 * Generic type definition that describes a 'not undefined' type.
 */
type Defined<T> = T extends undefined ? never : T

/**
 * Generic type guard function for values runtime-checked as defined.
 *
 * @param argument - The argument to check.
 *
 * @returns The boolean describing the assertion.
 * @remarks Uses the {@link Defined} type as returned value.
 */
function isDefined<T>(argument: T): argument is Defined<T> {
  return !!argument
}

const foo: string | undefined
isDefined(foo)
      ? foo //string
      : foo //undefined (not string | undefined anymore)
0

Okay, I found the solution that are works and types-friendly enough:

tl;dr

function isDefined<T>(value: T | undefined | null): value is T {
  return <T>value !== undefined && <T>value !== null;
}

Why?

In this way isDefined() will respect variable's type and the following code would know take this check in account.

Example 1 - basik check:

function getFoo(foo: string): void { 
  //
}

function getBar(bar: string| undefined) {   
  getFoo(bar); //ERROR: "bar" can be undefined
  if (isDefined(bar)) {
    getFoo(bar); // Ok now, typescript knows that "bar' is defined
  }
}

Example 2 - types respect:

function getFoo(foo: string): void { 
  //
}

function getBar(bar: number | undefined) {
  getFoo(bar); // ERROR: "number | undefined" is not assignable to "string"
  if (isDefined(bar)) {
    getFoo(bar); // ERROR: "number" is not assignable to "string", but it's ok - we know it's number
  }
}
S Panfilov
  • 16,641
  • 17
  • 74
  • 96