Exclusive to TypeScript, enums let us define a list of named constants. This can make code easier to understand as we document distinct cases.
Projects created by Angular CLI use TypeScript. This means we write our Angular project code in TypeScript.
TypeScript is a superset of JavaScript. It includes and it’s compatible with JavaScript features. Also, TypeScript includes enums as a built-in feature.
Enums are exclusive to TypeScript. We can use them to define a list of named constants. This lets us create easier-to-understand code by documenting distinct cases. TypeScript includes numeric and string-based enums.
In this article, we’ll look at how to work with TypeScript enums in our Angular apps.
Before we can work with enums in our Angular app, we have to learn how to define and use enums in our TypeScript code.
We define enums with the enum
keyword. For instance, we write:
enum Answer {
No = 0,
Yes = 1,
}
to define the Answer
enum that has the No
and Yes
values. No
is set to 0 and Yes
is set to 1.
We can define enums without assigning each member to a value. So we can write:
enum Answer {
No,
Yes,
}
to define enums. Then No
is mapped to 0 and Yes
is mapped to 1 automatically.
Also, we can assign the first value to the number we want and then the rest of the members will be assigned to the numbers that come after the first number.
For example, if we have:
enum E {
X = 1,
Y,
Z,
}
Y
is set to 2 and Z
is set to 3 because the TypeScript compiler will assign the values that are one bigger than the previously assigned value automatically if we assign the first member to the value we want.
We can also set each member to a value returned by a function. For example, we write:
const getSomeValue = (val: number) => val;
enum Answer {
No = getSomeValue(0),
Yes = getSomeValue(1),
}
to define the getSomeValue
function that takes a number and returns it.
Then we call getSomeValue
to return the argument that was pass in and use the returned value as the value of the enum case.
We can also assign string values to enum members. For instance, we write:
enum Answer {
No = "No",
Yes = "Yes",
}
to set No
to "No"
and Yes
to "Yes"
.
String enums don’t have an auto-incrementing behavior for assigning values to each case like numeric enums do.
We can also assign enum expressions to enum members. For instance, we write:
enum E {
X = 1,
Y = 2,
Z = "abc".length,
}
to set member Z
to "abc".length
, which returns 3.
To access enum values, we use the dot notation. For instance, we write:
enum E {
X = 1,
Y = 2,
Z = "abc".length,
}
console.log(E.X);
to access the value of E.X
. So the console would log 1 if we run the code.
We can use enum members as types. For instance, we write:
enum Fruit {
Orange,
Banana,
}
interface Orange {
kind: Fruit.Orange;
color: string;
}
We use the Fruit.Orange
value as the type for the kind
property in the Orange
interface.
So kind
’s only possible value is Fruit.Orange
.
TypeScript also has const
enums. const
enums are enums that can’t have computed members.
So we can write something like:
const enum Enum {
X = 1,
Y = X * 2,
}
where the value of Y
is derived from member X
.
const
enums can’t have computed members since no extra code is generated for computing the values of the enums at compile time.
Since Angular projects use TypeScript, we can add enums into our project code.
To do this, we just define a TypeScript enum as we do in the previous section. For instance, we write:
app.component.ts
import { Component } from "@angular/core";
enum MyEnum {
FirstValue,
SecondValue,
}
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {
foo = MyEnum.FirstValue;
bar = MyEnum.SecondValue;
}
to define MyEnum
in our component.
Then we set foo
and bar
to the member values of the MyEnum
enum.
Next, in app.component.html, we write:
<div>
<p>{{ foo }}</p>
<p>{{ bar }}</p>
</div>
to interpolate the values of foo
and bar
to show the values of them on the page.
We should see 0 for foo
and 1 for bar
since the first enum member is assigned 0 by default if we don’t assign it any value.
And the subsequent members have values that are incremented from the previous member.
The types for foo
and bar
are inferred directly from the values we assigned to them. So the TypeScript compiler knows they’re numbers.
We can also use the enum directly in our template.
For instance, in app.component.ts, we write:
import { Component } from "@angular/core";
enum MyEnum {
FirstValue,
SecondValue,
}
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {
enum: typeof MyEnum = MyEnum;
}
Then in app.component.html, we write:
<div>
<p>{{ enum.FirstValue }}</p>
<p>{{ enum.SecondValue }}</p>
</div>
We assign the type for enum
to the type for MyEnum
, which we get from typeof MyEnum
. And we assign MyEnum
to enum
as a value.
Then we show the values of enum.FirstValue
and enum.SecondValue
directly. And so, we should see 0 and 1 as their values respectively.
We can also use enums in component methods. For example, we write:
import { Component } from "@angular/core";
enum MyEnum {
FirstValue,
SecondValue,
}
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {
enum: typeof MyEnum = MyEnum;
ngOnInit() {
console.log(this.enum.FirstValue);
}
}
to log the value of this.enum.FirstValue
in the ngOnInit
method.
We should then see 0 logged when the component loads.
Also, we can use enums in directives. For example, we write:
app.component.ts
import { Component } from "@angular/core";
enum MyEnum {
FirstValue,
SecondValue,
}
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {
enum: typeof MyEnum = MyEnum;
val: number = MyEnum.FirstValue;
onClick() {
this.val =
this.val === MyEnum.FirstValue ? MyEnum.SecondValue : MyEnum.FirstValue;
}
}
to add the val
instance variable into AppComponent
.
Then we add the onClick
method that sets the val
instance variable to MyEnum.SecondValue
if its original value is MyEnum.FirstValue
and vice versa.
Next, in app.component.html, we write:
<div>
<button (click)="onClick()">click me</button>
<p *ngIf="val === enum.FirstValue">foo</p>
<p *ngIf="val === enum.SecondValue">bar</p>
</div>
to add a button that sets the click event handler of the button to the onClick
method.
And then we add two p
elements that are displayed if val
is equal to enum.FirstValue
and enum.SecondValue
, respectively.
As a result, when we click the button, we toggle between foo
and bar
.
Since val
and the MyEnum
member values are all numbers, we can compare them with ===
directly.
We can rewrite the app.component.html file by replacing *ngIf
with [ngSwitch]
and *ngSwitchCase
.
To do this, we write:
app.component.html
<div>
<button (click)="onClick()">click me</button>
<div [ngSwitch]="val">
<p *ngSwitchCase="enum.FirstValue">foo</p>
<p *ngSwitchCase="enum.SecondValue">bar</p>
</div>
</div>
to use the [ngSwitch]
directive to compare val
with the enum
member values specified as the *ngSwitchCase
directive values.
And we keep app.component.ts the same.
We get the same result as we have previously since we do the same comparisons with the same variables. All we did is to replace *ngIf
with [ngSwitch]
and *ngSwitchCase
to reduce repetition.
We can use code like anything we have above in any other kinds of Angular code files like directives, tests, modules, etc.
Because projects created by Angular CLI use TypeScript, we write our Angular project code in TypeScript. TypeScript is a superset of JavaScript that includes all modern JavaScript features with lots of TypeScript-exclusive features that make programming easier.
Enums are one of the features exclusive to TypeScript. We can use them to define a list of named constants, which lets us create easier-to-understand code by documenting distinct cases.
TypeScript includes numeric and string-based enums. And we can also assign computed values to non-const enums.
We can easily incorporate enums into Angular code like components and use them as values for directives.
Read more about directives, starting with NgFor in our Angular Basics series.
John Au-Yeung is a frontend developer with 6+ years of experience. He is an avid blogger (visit his site at https://thewebdev.info/) and the author of Vue.js 3 By Example.