Why aren't enums that can be derived supported?

Is there a way to create an enum that is a subset of another enum?

Sometimes it would be useful to have an enum that is a subset of another Enum with the same values at run time but under a different name.

Are there better ways to handle this scenario?

TypeScript

enum Original {
    value = "value",
    other = "other"
}

enum Derived {
    value = Original.value
}

const test: Original = Derived.value;

Generated JavaScript

"use strict";
var Original;
(function (Original) {
    Original["value"] = "value";
    Original["other"] = "other";
})(Original || (Original = {}));
var Derived;
(function (Derived) {
    Derived["value"] = "value";
})(Derived || (Derived = {}));
const test = Derived.value;

It would be more convenient if instead of assigning a static constant to the Derived enum, the value was derived from the Original enum at run time.

Possibilities:

  • Replacement: Due to being derived from an existing enum, compilation can replace the Derived values with the Original values. This eliminates the need to create a separate Derived object in the JavaScript output.

Example Replacement:

"use strict";
var Original;
(function (Original) {
    Original["value"] = "value";
    Original["other"] = "other";
})(Original || (Original = {}));

const test = Original.value;

Answer №1

An easy approach to achieve this is by creating a subtype of the enum using a union:

enum Original {
    foo = "foo",
    bar = "bar",
    baz = "baz",
}

type Derived = Original.foo | Original.bar;

If you want to be able to write Derived.foo, you can leverage a helper function to generate objects representing enum subtypes:

type ValueOf<T> = T[keyof T];

function enumSubtype<T, K extends keyof T>(e: T, keys: K[]): Pick<T, K> {
    const out = {} as Pick<T, K>;
    for (let k of keys) {
        out[k] = e[k];
    }
    return out;
}

const Derived = enumSubtype(Original, ['foo', 'bar']);
type Derived = ValueOf<typeof Derived>;

The type Derived represents Original.foo | Original.bar.

Playground Link

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

Is it possible to restrict optionality in Typescript interfaces based on a boolean value?

Currently, I am working on an interface where I need to implement the following structure: export interface Passenger { id: number, name: string, checkedIn: boolean, checkedInDate?: Date // <- Is it possible to make this f ...

What is the cause of the error message "property 'map' is undefined"?

I am currently working on a service that looks like this: public getUsers() { return this.httpClient.get(environment.BASE_URL + `api/all`); } In my component, I have implemented the ngx-bootstrap table to display the user data. import { Component, OnI ...

Deactivate a variable during operation

I have a unique component called book-smart that has the functionality to display either book-update or book-create based on the availability of a BookDto in my book.service. The update feature can be accessed by clicking a button in a table, while the cre ...

The Aurelia application encounters a "Maximum call stack size exceeded" error while trying to bind FullCalendar

I am currently working on setting up a JQuery plugin (FullCalendar) within my Aurelia application, which is built using TypeScript. I am relatively new to web development and just trying to get a basic example up and running. To start off, I utilized this ...

Error: Call stack size limit reached in Template Literal Type

I encountered an error that says: ERROR in RangeError: Maximum call stack size exceeded at getResolvedBaseConstraint (/project/node_modules/typescript/lib/typescript.js:53262:43) at getBaseConstraintOfType (/project/node_modules/typescript/lib/type ...

Error: User authentication failed: username: `name` field is mandatory

While developing the backend of my app, I have integrated mongoose and Next.js. My current challenge is implementing a push function to add a new user to the database. As I am still relatively new to using mongoose, especially with typescript, I am followi ...

Converting a TypeScript class to a plain JavaScript object using class-transformer

I have a few instances of TypeScript classes in my Angular app that I need to save to Firebase. However, Firebase does not support custom classes, so I stumbled upon this library: https://github.com/typestack/class-transformer which seems to be a good fit ...

What specific element is being targeted when a directive injects a ViewContainerRef?

What specific element is associated with a ViewContainerRef when injected into a directive? Take this scenario, where we have the following template: template `<div><span vcdirective></span></div>` Now, if the constructor for the ...

What is the best way to add a service to a view component?

I am facing an issue with my layout component where I am trying to inject a service, but it is coming up as undefined in my code snippet below: import {BaseLayout, LogEvent, Layout} from "ts-log-debug"; import {formatLogData} from "@tsed/common/node_modul ...

Generating a composer method in TypeScript (Flow $Composer)

While flow supports $Compose functions, the equivalent mechanism seems to be missing in TypeScript. The closest thing I could find in TypeScript is something like https://github.com/reactjs/redux/blob/master/index.d.ts#L416-L460. Is there a native equivale ...

Incorporate the {{ }} syntax to implement the Function

Can a function, such as toLocaleLowerCase(), be used inside {{ }}? If not, is there an alternative method for achieving this? <div *ngFor="let item of elements| keyvalue :originalOrder" class="row mt-3"> <label class=" ...

struggling to access the value of [(ngModel)] within Angular 6 component

When working in an HTML file, I am using ngModel to retrieve a value that I want to utilize in my component. edit-customer.component.html <input id="userInfoEmail" type="text" class="form-control" value="{{userInfo.email}}" [(ngModel)]="userInfo.email ...

What is the best way to design functions that can return a combination of explicit types and implicit types?

When looking at the code provided below, function system(): ISavable & ISerializable { return { num: 1, // error! save() {}, load() {}, serialize() {}, deserialize() {}, } } interface ISavable { sa ...

Securing Angular 2 routes with Firebase authentication using AuthGuard

Attempting to create an AuthGuard for Angular 2 routes with Firebase Auth integration. This is the implementation of the AuthGuard Service: import { Injectable } from '@angular/core'; import { CanActivate, Router, Activated ...

Showing information from a JSON dataset of users once a specific User ID has been chosen

My task involves displaying user data from an array and then showing the details of the selected user. I attempted to achieve this with the following code: users = USERS; // contains data selectedUser: User; constructor() { } ngOnInit() { } onSelect(i ...

Is it possible to extend the Object class in order to automatically initialize a property when it is being modified?

My experience with various programming languages leads me to believe that the answer is likely a resounding no, except for PHP which had some peculiar cases like $someArray['nonexistentKey']++. I'm interested in creating a sparse object whe ...

Unusual TypeScript Syntax

While examining a TypeScript function designed to calculate average run time, I stumbled upon some unfamiliar syntax: func averageRuntimeInSeconds(runs []Run) float64 { var totalTime int var failedRuns int for _, run := range runs { ...

How can the adapter pattern be implemented in Angular when dealing with an HTTP response containing an array of objects?

Using the adapter pattern in Angular, I have successfully adapted Http response to an 'Invoice' object. However, I am facing a challenge when one of the properties inside the 'Item' is an array. In this scenario, the 'items' ...

What is the necessity behind keeping makeStyles and createStyles separate in Material UI with TypeScript?

Dealing with TypeScript issues in Material UI has been a frequent task for me, and I find it frustrating that styling components requires combining two different functions to create a hook every time. While I could use a snippet to simplify the process, it ...

What happens when i18next's fallbackLng takes precedence over changeLanguage?

I am currently developing a Node.js app with support for multi-language functionality based on the URL query string. I have implemented the i18next module in my project. Below is a snippet from my main index.ts file: ... import i18next from 'i18next& ...