The variable type does not align with the export type

My TypeScript project includes a file that loads environment variables and exports them:

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 am puzzled as to why the exported type is string | undefined even though I have checked for its existence. When I hover over VARIABLE0 after the check in VS Code, it shows as string, but during export, it is string | undefined. This inconsistency causes inconvenience in other parts of my code where I need to use these variables because I have to add ? and ! in numerous places (e.g.,

const length = VARIABLE0?.length!
instead of const length = VARIABLE0.length).

Is there a way to export it as string without the undefined part?

One approach I can think of 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,
};

However, this solution may not be optimal as it is quite verbose, especially since I have around 10 variables to export in a similar manner.

Answer №1

If you want to narrow down process.env, one approach is to utilize an assertion function. Here's an example:

function validateConfig<T extends string>(
    env: NodeJS.ProcessEnv,
    required: readonly T[],  // Using 'readonly' enables const assertion
): 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 apply this like so:

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

Either an error will be thrown or both process.env.VARIABLE0 and process.env.VARIABLE1 will be of type string. Subsequently, you can do things like:

const { VARIABLE0, VARIABLE1 } = process.env;

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

Check out this Playground

Note: When the required argument is typed as string[], the result will be

NodeJS.ProcessEnv & Record<string, string>
. This informs the compiler that all possible environment variables will exist - either explicitly list the required variables or use as const to obtain a more specific string union array/tuple type.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The term "Exports" has not been defined

I'm currently facing a challenge trying to develop an Angular application based on my initial app. The process is not as smooth as I had hoped. Here's the current setup: index.html <!DOCTYPE html> <html> <head> <base h ...

Removing Angular Template space highlights in WebStorm can be done easily with a few simple steps

Is there a way to remove space highlights in Angular / TypeScript using WebStorm 2019? https://i.stack.imgur.com/vfudR.jpg Many thanks, Sean ...

Performing DTO validation in the controller before passing data to the service

My current challenge involves implementing validation in a PUT request to update data stored in MongoDB: DTO: export enum reportFields { 'startDate', 'targetDateOfCompletion', 'duration', } export class updateS ...

Typescript in Firebase Functions organization

Struggling with typescript organization in my firebase functions. I'm fine keeping trigger functions in index.ts for now, but need help organizing other utility functions elsewhere. Current index.ts setup: import * as functions from 'firebase-f ...

Swiping in Angular2 gets a new twist with Swiper typings

Having trouble importing typings for Swiper into my Angular 2 project. After installing Swiper and its typings using npm, I tried including Swiper in my component like this: import { Swiper } from 'swiper'; However, Atom displays an error: ...

Connecting the SelectedItem of a listbox in ngPrime to an Observable Collection in Angular2

I am facing an issue while trying to use the ngPrime listbox in Angular2. I have a scenario where I am fetching an array of objects from Firebase as an observable and attempting to display it correctly in the listbox. <div *ngIf="addContactDialogVisibl ...

Developing applications using ReactJS with Typescript can sometimes lead to errors, such as the "onclick does not exist on type x

In the code snippet below, I have a method that renders a delete icon and is used in my main container. Everything functions correctly except for a small cosmetic issue related to the type any that I am struggling to identify. import React from 'reac ...

Invoke the function once the database information has been retrieved

I am new to Node.js and I am attempting to execute a function after running a select query using the code below: private displayUserInfo(): any { let connect = this.connect(); connect.connect(function(err: any) { if (err) throw err; ...

Excessive geolocation position responses in Angular 5

I am trying to implement an Angular 5 component that will continuously fetch my current location every 3 seconds if it has changed. Here is a snippet of my code: export class WorkComponent implements OnInit { constructor(private userService: UserService ...

Typescript Error: Trying to access a property that is undefined

I am a beginner in typescript and believe that the issue I am facing is related to typescript. Currently, I am working on an Ionic app where I have a function setwall() being called from home.html. The setwall() function is defined in home.ts. However, whe ...

Problem with timing in token interceptor and authentication guard due to injected service

Currently, I am facing an issue where I need to retrieve URLs for the auth service hosted on AWS by reading a config.json file. In order to accomplish this, I created a config service that reads the config file and added it as a provider in app.module. Eve ...

When passing an invalid value to the Props in TypeScript, no errors are being thrown

const enum ColumnValues { one = 1, two = 2, three = 3, } interface Props { style?: StyleProp<ViewStyle>; title?: string; titleContainerStyle?: StyleProp<ViewStyle>; titleStyle?: StyleProp<TextStyle>; textInputStyle?: Styl ...

The correct procedure for refreshing a page in Angular 8

Note: I found some code snippets online but, after testing them out, I have doubts about their reliability due to inconsistencies. In my script, I have developed two utility functions - one for moving to the parent node and another for reloading the curre ...

Can metadata be attached to data models in Angular for annotation purposes?

Looking to add some metadata annotations to a simple data model export class Certification { title: string; certificationType?: CertificationType; validTo?: number; description?: string; externalIdentifier: Guid; constructor() { ...

rxjs - monitoring several observables and triggering a response upon any alteration

Is there a way to watch multiple observables and execute a function whenever any of them change? I am looking for a solution similar to the functionality of zip, but without requiring every observable to update its value. Also, forkJoin isn't suitable ...

Nock does not capture the requests - Error: Failed to resolve address ENOTFOUND

Let me provide an overview of the structure in place. Jest is utilized for executing the testing process. Within my jest.config.json file, I incorporate the following line: "globalSetup": "<rootDir>/__tests__/setup.js", Inside setup.js, you will ...

What is the best way to implement Angular translation for multiple values in a typescript file, while also incorporating parameters?

this.snackBar.open( `Only files of size less than ${this.fileSizeAllowed}KB are allowed`, this.translate.instant('USER_REG.close'), { panelClass: 'errorSnackbar', ...

Conditional validation in Typescript based on the nullability of a field

I have come across the following code snippet: type DomainFieldDefinition<T> = { required?: boolean } type DomainDefinition<F, M> = { fields?: { [K in keyof F]: DomainFieldDefinition<F[K]> }, methods?: { [K in keyof M]: M[K] & ...

Sorting TypeScript types by required properties first

Can anyone recommend a plugin or ESLint rule that can automatically sort types by assuming required fields come first, followed by optional fields? Here's an example before: type TExampleSorting = { title?: string; value?: number; text: string; ...

What is the best way to create a dynamic URL linking to an external site in Angular 5?

When attempting to create a link like this: <a [href]="getUrl()">click me</a> getUrl() { return this.domSanitizer.bypassSecurityTrustUrl('http://sampleUrl.com'); } The link is not clickable. When hovering over the ...