provocationofmind.com

Understanding TypeScript Enums and Their Alternatives

Written on

TypeScript enums, or enumerated types, represent a unique data structure that can encapsulate a set of constants. While enums are not exclusive to TypeScript, their compilation into JavaScript offers a compelling reason to examine their utility in this language.

In this concise and practical guide, we will investigate the compilation of enums to JavaScript, the potential inconsistencies in the resulting code, ways to utilize them more effectively, and an alternative approach to enums.

Let’s dive in:

TypeScript Enums

To define an enum in TypeScript, you can use the following syntax:

enum Protocol {

HTTP,

HTTPS,

WS

}

In this case, TypeScript automatically assigns numeric values to these constants, starting at 0.

A key advantage of enums is their dual role as types, allowing us to enforce type safety during compilation while retaining type information at runtime. This contrasts with conventional TypeScript types, which are removed during execution.

We can leverage enums as types and build logic around their values, as demonstrated below:

function printProtocol(protocol: Protocol): void {

switch (protocol) {

case Protocol.HTTP:

console.log("web insecure");

break;

case Protocol.HTTPS:

console.log("web secure");

break;

case Protocol.WS:

console.log("socket protocol");

break;

default:

console.log("Unknown protocol");

}

}

printProtocol(Protocol.HTTP);

The Challenge

JavaScript does not inherently support enums. Although there is a TC39 proposal in the works, as of this writing, enums have not yet been integrated into the core language.

Consequently, when TypeScript code is compiled into JavaScript, enums are transformed into bidirectionally accessible objects as follows:

{

0: "HTTP",

1: "HTTPS",

2: "WS",

HTTP: 0,

HTTPS: 1,

WS: 2

}

While this structure provides access from multiple points, it leads to redundancy and potential confusion. The complexity increases further when we assign string values to an enum:

Enums with String Values

Let’s assign string values to our previous enum example:

enum Protocol {

HTTP = "http",

HTTPS = "https",

WS = "websocket"

}

This compiles into a cleaner JavaScript object:

{

HTTP: "http",

HTTPS: "https",

WS: "websocket"

}

While this representation is clearer, it highlights the variance in compiled output based on the value types assigned to the enum constituents. Depending on your specific needs, this inconsistency can present challenges.

An Alternative Approach: The Const Assertion

The as const keyword in TypeScript, known as const assertion, provides a reliable alternative to enums by producing consistent compiled JavaScript, regardless of the value types assigned to the constants.

This can be implemented as follows:

const Protocol = {

HTTP: 0,

HTTPS: 1,

WS: 2

} as const;

Since this is treated as a constant, the bidirectional object structure is eliminated, resulting in consistent output irrespective of whether values are numeric or string-based.

The compiled JavaScript will yield:

{

HTTP: 0,

HTTPS: 1,

WS: 2

}

Deriving Types from Const Assertions

While this approach is advantageous, it limits our ability to use Protocol as a type in its current form. Attempting to do so will result in a compiler error:

'Protocol' refers to a value, but is being used as a type here.

Did you mean 'typeof Protocol'?

Fortunately, TypeScript provides a way to navigate around this limitation. A const assertion also narrows the type of the created object, enabling us to derive specific types as follows:

const Protocol = {

HTTP: 0,

HTTPS: 1,

WS: 2

} as const;

type Protocol = keyof typeof Protocol;

type ProtocolValues = typeof Protocol[keyof typeof Protocol];

function printProtocol(protocol: ProtocolValues): void {

switch (protocol) {

case Protocol.HTTP:

console.log("web insecure");

break;

case Protocol.HTTPS:

console.log("web secure");

break;

case Protocol.WS:

console.log("socket protocol");

break;

default:

console.log("Unknown protocol");

}

}

printProtocol(Protocol.HTTP);

The Protocol type can now take on values of "HTTP" | "HTTPS" | "WS", while the ProtocolValues type can be 0 | 1 | 2.

This allows for precise type definitions while maintaining runtime logic consistency. Additionally, we can use string values in our constants:

const Protocol = {

HTTP: "http",

HTTPS: "https",

WS: "websocket"

} as const;

This would update our ProtocolValues to "http" | "https" | "websocket".

Another interesting aspect is that mixed data types can now be assigned to our constants:

const Protocol = {

HTTP: "http",

HTTPS: 2,

WS: "websocket"

} as const;

This would adjust our ProtocolValues type to the narrowed type of "http" | 2 | "websocket".

Video Demo

Conclusion

In this article, we explored TypeScript enums, their compilation to JavaScript, and an alternative known as const assertion. This method not only simplifies refactoring—allowing updates in one location to automatically adjust type inference—but also preserves the benefits of enums without the inconsistencies in compiled code.

If you are passionate about software engineering and keen on discovering alternative strategies for effective software design and development, consider following me for more insightful and practical technical content.

Thank you for reading, and I look forward to sharing more in my next article!

Cheers :)

Share the page:

Twitter Facebook Reddit LinkIn

-----------------------

Recent Post:

Finding True Meaning Beyond Materialism in a Capitalist World

Explore the spiritual challenges of capitalism and the quest for deeper meaning in a materialistic society.

Empower Your Life: 21 Essential Lessons for Growth

Discover 21 impactful lessons to transform your life and embrace personal growth.

Finding Inner Peace in a Fast-Paced World: A Mindfulness Journey

Exploring mindfulness and practical steps to achieve inner peace amidst life's chaos.

Finding Co-Founders for Your Startup: Essential Tips for 2024

Explore effective strategies and platforms to find co-founders for your startup or business in 2024.

Essential Tips for Publishing Success on Medium

Discover essential checks before publishing on Medium to enhance your story’s visibility and impact.

Innovative Mac Applications You Shouldn't Miss in 2024

Discover the latest must-have Mac apps that enhance productivity and streamline your workflow.

The Journey from Shame to Self-Discovery: Breaking Free from Toxicity

A personal story of overcoming shame and rethinking self-improvement.

# Embracing Pain: A Journey Towards Healing and Clarity

Discover how embracing pain can lead to healing and personal growth.