If you guy need to declare your enum
in definition file you may encounter a weird behavior and lead to something like this
/// module A
/// types.d.ts
export enum MyEnumA {
A = "A"
}
/// module B
/// main.ts
import { MyEnumA } from 'A'
console.log(MyEnumA.A)
// TypeError: cannot read property 'A' of undefined
Why?
In the nutshell, Definition file cannot be reference as value and that is why they call it 'Ambient'
How to properly solve it?
const enum
solution (Not recommended)
If your project have a very simple setup. You may able to use the typescript feature call const enum
which
const
as a prefix ofenum
will turn thisenum
into an inline constant in compiler time.
/// module A
/// types.d.ts
export const enum MyEnumA {
A = "A"
}
/// module B
/// main.ts
import { MyEnumA } from 'A'
console.log(MyEnumA.A)
/// module B compiled
/// main.js
console.log("A") // <<< here is the hardcoded value from enum
But why this approach is not recommended?
- this approach does not support
isolatedModule
option - as
MyEnumA.A
is transpile into a hardcoded value. ifmodule B
enum value is change, you need to recompilemodule A
again to update the hardcoded value - Typescript team does not recommend it https://www.typescriptlang.org/docs/handbook/enums.html#const-enum-pitfalls
Declare ambient value in global scope (Recommended)
The proper solution is to assign this enum value ambient. As ambient is just an abstraction, in the implementation file you need to assign this value as you declare in ambient too.
So we will declare enum
in definition file as an ambient and assign value into global scope variable
/// module A
/// types.d.ts
declare enum MyEnumAValue { // ambient enum
A = "A"
}
declare var MyEnumA: typeof MyEnumAValue // ambient value
/// module B
/// types.ts as ambient value file
enum MyEnumAValue {
A = 'A'
}
window.MyEnumA = MyEnumAValue; /// this will be checking with ambient if enum value is consistent with ambient enum
// or
global.MyEnumA = MyEnumAValue;
/// main.ts
import 'A'
console.log(MyEnumA.A)
Here is how the type checking work
Consistent
Inconsistent
Summary
If you want to use a type definition file and you want to declare enum in it.
in the implementation file you need to assign the value as you declare in the ambient too.
The best way to do it is assign the enum value to global scope variable.
Top comments (3)
Hey, thank you for your article!
Why do you need to declare enum in declaration file?
@beraliv There is sometime that we may need to use our module as ambient module 🤓
For my benefit, could you please give me one example so I will understand you better?
I didn't use ambient enums before. Maybe you have an example in OSS library where I can have a look at the usage?