Cannot access enum before initialization, react typescript

Viewed 862

In my program, I have lots of files with enum definitions like this and some files which join enums together. The enums are string-enums, so the indexing is not part of the problem. When I join enums together I get the error "Cannot access 'Both' before initialization". There are also circular imports, since I am using the combined enum in the first file. I understand the error message, however I import the files containing the necessary enums before defining 'Both'. Is this a typescript bug or am I missing something? I am using typescript in a React environment, so maybe I am missing the right tsconfig lines.



// firstFile.ts

export enum One
{
    A,
    B,
}

export enum Two
{
    C = 2,
    D,
}


// secondFile.ts, throws error

import { One, Two } from './firstFile';

export const Both = 
{
    ...One,
    ...Two,
}

1 Answers

Circular dependencies are allowed in TypeScript (and ECMAScript as well), the static resolution of import and export clauses will work, but you have to be careful of the execution order of the files, depending on the entry point. Indeed, when a circular dependency is met, the entry point acts as the trunk of the dependency tree, so the other files execute before. When a file executes all of its top-level code executes, and will fail if it meets unresolved variables.

Now let's see what happens in your particular case. Your code transpiles to something like this:

firstFile.ts

import { Both } from "./secondFile.js";
export var One;
(function (One) {
    One[One["A"] = 0] = "A";
    One[One["B"] = 1] = "B";
})(One || (One = {}));
export var Two;
(function (Two) {
    Two[Two["C"] = 2] = "C";
    Two[Two["D"] = 3] = "D";
})(Two || (Two = {}));

secondFile.ts

import { One, Two } from './firstFile.js';
export const Both = Object.assign(Object.assign({}, One), Two);

If you use secondFile.ts as the entry point, firstFile.ts will execute first and will not throw any error because Both is unused in firstFile.ts.

However, if you add let's say a console.log(Both.A) at the end of firstFile.ts it will fail with a Cannot access 'Both' before initialization error because secondFile.ts has not executed yet, so Both is exported but not initialized.

Related