Home > Software design >  Typescript: undefined is not assignable to return while undefined cannot be returned
Typescript: undefined is not assignable to return while undefined cannot be returned

Time:12-03

I have following piece of code that pulls environment variables via dotenv, can substitute it, if it does not exist and defaultValue is passed or throws error if neither of them contain value. This creates a scenario where execution either crashes or it returns valid value.

const getEnvironmentVariable = (
  variable: string,
  defaultValue?: string|number,
): string | number => {
  if((process.env[variable] === undefined) && defaultValue === undefined){
    // eslint-disable-next-line max-len
    throw new Error(`Mandatory environment variable ${variable} was not set.`)  
  }
  
  if(
    process.env[variable] === undefined 
    && defaultValue !== undefined
  ) {
    // eslint-disable-next-line no-console, max-len
    console.info(`Environment variable ${variable} was not set. Using default: ${defaultValue}`)
  }
  return process.env[variable] ?? defaultValue
}

But I am getting following error on return, even tho it will never happen, that undefined will be returned.

Type 'string | undefined' is not assignable to type 'string | number'. Type 'undefined' is not assignable to type 'string | number'.

CodePudding user response:

Typescript doesn't understand the concept of: "If this variable is undefined, it means that the other one is not."

To Typescript this just means the both of the variables can be undefined.

Another issue you might encounter is that process.env[variable] will always return string | undefined even though you checked in on a previous line. you should therefore store it in a const. Here is an example that should work:

const getEnvironmentVariable = (
  variable: string,
  defaultValue?: string | number,
): string | number => {
  const environmentVariable = process.env[variable]
  
  if (environmentVariable === undefined) {
    if (defaultValue === undefined) {
      throw new Error(
        `Mandatory environment variable ${variable} was not set.`,
      );
    }
    console.info(
      `Environment variable ${variable} was not set. Using default: ${defaultValue}`
    );
    return defaultValue;
  }
  return environmentVariable;
};

CodePudding user response:

After the first if, defaultValue is still string | number | undefined because of the and.

Since process.env[variable] === undefined could be false, the second operand is not checked.

The same for the second if, in order to check for defaultValue === undefined you have to split the ifs:

const getEnvironmentVariable = (
  variable: string,
  defaultValue?: string|number,
): string | number => {
  if(process.env[variable] === undefined) {

    if(defaultValue === undefined) {
      // eslint-disable-next-line max-len
      throw new Error(`Mandatory environment variable ${variable} was not set.`)  
    }

    if(defaultValue) {
      console.info(`Environment variable ${variable} was not set. Using default: ${defaultValue}`)
      return defaultValue;
    }
  }
  
  return process.env[variable];
}
  • Related