Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Export type not matching variable type

I have a TypeScript project with a file that loads env variables and export it:

const.ts:

const {
  VARIABLE0, // type of VARIABLE0 is string | undefined
  VARIABLE1,
} = process.env;

if (!VARIABLE0 || !VARIABLE1) {
  throw new Error('Invalid env');
}

console.log(VARIABLE0); // type of VARIABLE0 is string
console.log(VARIABLE0.length);

export {
  VARIABLE0, // type VARIABLE0 is string | undefined
  VARIABLE1,
};

I don’t understand why the exported type is string | undefined because before, I check that it is defined. On VS Code If I hover on VARIABLE0 after the check, it is string but if I hover on the export, it is string | undefined. It is anoying on other part of my code that uses this variables because I have to add ? and ! in many places (for instance const length = VARIABLE0?.length! instead of const length = VARIABLE0.length).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Is there a way to export it as string and not string | undefined?

One way I see is:

const {
  VARIABLE0: VARIABLE0_TEMP, VARIABLE1: VARIABLE1_TEMP,
} = process.env;

if (!VARIABLE0_TEMP || !VARIABLE1_TEMP) {
  throw new Error('Invalid env');
}

const VARIABLE0 = <string>VARIABLE0_TEMP;
const VARIABLE1 = <string>VARIABLE1_TEMP;

export {
  VARIABLE0, VARIABLE1,
};

But it’s probably not the best solution (it is quite verbose and I actually have around 10 variables to export like this).

>Solution :

One way to do it is to use an assertion function to narrow process.env. For example:

function validateConfig<T extends string>(
    env: NodeJS.ProcessEnv,
    required: readonly T[],  // readonly allows arg to be const-asserted
): asserts env is NodeJS.ProcessEnv & Record<T, string> {
    const missing = required.filter((envVar) => !(envVar in env));
    if (missing.length > 0) {
        throw new Error(`missing required env vars: ${missing.join(", ")}`);
    }
}

Now you can use this like:

validateConfig(process.env, [
    "VARIABLE0",
    "VARIABLE1",
]);

and either the error gets thrown or process.env.VARIABLE0 and process.env.VARIABLE1 are both string, so you can then e.g.:

const { VARIABLE0, VARIABLE1 } = process.env;

export {
  VARIABLE0, // type VARIABLE0 is string
  VARIABLE1,
};

Playground

Note that if the required argument is typed as string[] the result will be NodeJS.ProcessEnv & Record<string, string>, i.e. it tells the compiler that every possible environment variable will exist – either inline the list of required variables or type it as const to get the narrower string union array/tuple type.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading