Is it possible to ensure that all values from a specific type are represented in an enum collection?

I have a Prisma enum that I've defined (not in TypeScript), and I'm curious if it's possible to synchronize a TypeScript String enum with the generated Type from the Prisma Client. Here are the key details:

export const GroupInvitationStatus: {
  Pending: 'Pending',
  Accepted: 'Accepted',
  Declined: 'Declined'
};

export type GroupInvitationStatus = (typeof GroupInvitationStatus)[keyof typeof GroupInvitationStatus]

Upon importing GroupInvitationStatus from the Prisma Client, I noticed its contents:

(alias) type GroupInvitationStatus = "Pending" | "Accepted" | "Declined"

My aim is to ensure that every value in the Prisma enum (referenced through the imported type) is specified in my TypeScript string enum.

Is this achievable? I've reviewed the TypeScript documentation on enums and searched for solutions but haven't found one yet.

Is it too much? Should I just stick to using the type directly and skip defining an enum?

Update 1: I came across this solution from Stack Overflow that seems promising for my requirements.

Is there a way to dynamically generate enums on TypeScript based on Object Keys?

However, I am struggling to make TypeScript react to changes made in the Prisma Client, contained within the node modules.

While this alternative seems better, it doesn't address my specific situation. I'm starting to think that using the generated const instead of the type as an enum would work just as effectively.

New update: Here is a Code Sandbox with more context. In "prisma-client.ts," I mimic exports from a node module in my project, and in "target-file.enum.ts," I utilize the exports from the Prisma Client.

https://codesandbox.io/s/sweet-curran-n7ruyt?file=/src/target-file.enum.ts

Answer №1

Found on a Typescript playground

To see how it operates, check out the details provided here.

This functionality can be achieved by placing this snippet in a .d.ts file:

declare const GroupInvitationStatus: {
  Pending: 'Pending',
  Accepted: 'Accepted',
  Declined: 'Declined'
};

Essentially working as an enum, it is advised not to duplicate Enum for your own purpose.

Answer №2

In this guide, I will outline a method for creating what I refer to as "synthetic string enums": dynamic objects with read-only keys and values that are identical to each other, generated from a tuple of string literals. The types used in the creation process can be limited based on an existing string union (imported). While verbose due to TypeScript's nature, this approach offers flexibility and ensures type correctness.

The key element enabling this technique is a higher-order function that utilizes a generic type constraint to form an identity function where the input parameter conforms to the original type restriction.

I have extensively annotated the code to provide documentation within your codebase should you choose to implement it. If anything seems unclear or if errors are detected, feel free to seek clarification by leaving a comment.

I recommend exploring the code in the // import type {GroupInvitationStatus} from 'some_module_specifier'; // Example showing the imported content mentioned above: type GroupInvitationStatus = 'Accepted' | 'Declined' | 'Pending'; /** * Generates a new identity function that takes and returns a value, * triggering a compiler error if the value does not extend * the specified constraint. */ function createConstrainedIdentityFn <Constraint = never>(): <T extends Constraint>(value: T) => T { return value => value; } /** An approximation of TS's string enum runtime object type */ type StringEnumObj<StrUnion extends string> = { readonly [S in StrUnion]: S }; /** Converts a string tuple into an object with key-value pairs */ function objectFromTuple <T extends readonly string[]>( strings: T, ): StringEnumObj<T[number]> { return Object.fromEntries(strings.map(s => [s, s])) as StringEnumObj<T[number]>; // Type assertion required } // This part needs manual updating but aids in safe iteration over keys using string literals const groupInvitationStatusTuple = createConstrainedIdentityFn<readonly GroupInvitationStatus[]>()( ['Accepted', 'Declined', 'Pending'] as const, ); // Trying to use values beyond the imported union results in a compilation error. createConstrainedIdentityFn<readonly GroupInvitationStatus[]>()(['Accepted', 'Declined', 'Pending', 'nope'] as const); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Argument of type 'readonly ["Accepted", "Declined", "Pending", "nope"]' is not assignable to parameter of type 'readonly GroupInvitationStatus[]'. Type '"Accepted" | "Declined" | "Pending" | "nope"' is not assignable to type 'GroupInvitationStatus'. Type '"nope"' is not assignable to type 'GroupInvitationStatus'.(2345) */ // Continuing from where we left off earlier

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

Retrieve the accurate file name and line number from the stack: Error object in a JavaScript React Typescript application

My React application with TypeScript is currently running on localhost. I have implemented a try...catch block in my code to handle errors thrown by child components. I am trying to display the source of the error (such as file name, method, line number, ...

An Unexpected Typescript Error Occurred While Creating an RxCollection With RxDB

I'm new to RxDB and I've come across a strange Typescript error in my Electron project. Here are the relevant parts of my code: import RxDB, { RxCollection, RxDatabase } from "rxdb"; RxDB.plugin(require("pouchdb-adapter-idb") ...

"Using Angular and TypeScript to dynamically show or hide tabs based on the selected language on a website

When switching the language on the website, I want to display or hide a specific tab. If the language is set to German, then show the tab; if any other language is selected, hide it. Here's my code: ngOnInit(): void { this.translate.onLangChange.s ...

Is OnPush Change Detection failing to detect state changes?

Curious about the issue with the OnPush change detection strategy not functioning properly in this demonstration. My understanding is that OnPush change detection should activate when a property reference changes. To ensure this, a new array must be set e ...

When using TypeORM's save() method with an array of objects, the @PrimaryColumn() annotations are ignored, resulting

My current situation involves an entity called Point: @Entity() export class Point { @PrimaryGeneratedColumn('uuid') id: string; @IsUUID() @PrimaryColumn({ type: 'uuid', ...

Is there a way to incorporate several select choices using specific HTML?

I am currently trying to dynamically populate a select tag with multiple option tags based on custom HTML content. While I understand how to insert dynamic content with ng-content, my challenge lies in separating the dynamic content and wrapping it in mat ...

The attribute 'name' cannot be found within the class 'MyComponent'

I'm a beginner in Angular2 and I have no previous knowledge of version 1. Can you help me understand why this error is occurring and guide me on how to fix it? import { Component } from 'angular2/core'; @Component ({ selector: 'my- ...

Having trouble configuring Jest for TypeScript integration

I am currently implementing unit testing for a typescript project following the guidelines in this example: https://dev.to/muhajirdev/unit-testing-with-typescript-and-jest-2gln In my project, I have a file named main.ts that exports an isInternalLink func ...

What are the steps to styling a component with CSS Emotion?

I am facing an issue with using a theme with TypeScript in this component const buttonDisabled = css` color: ${({ theme }) => theme.color}; `; Is there a way to correctly type this component? Error: No overload matches this call. Overload 1 of 2, & ...

Why is it necessary to include a dollar sign before interpolation in Angular?

While diving into a tutorial, I stumbled upon a piece of code that piqued my curiosity. I grasped the concept that appending a dollar sign as a suffix indicates observability, but I wonder why the dollar sign was also prefixed to this.log(`updated hero i ...

Set up a personalized React component library with Material-UI integration by installing it as a private NPM package

I have been attempting to install the "Material-UI" library into my own private component library, which is an NPM package built with TypeScript. I have customized some of the MUI components and imported them into another application from my package. Howe ...

The array used within the useEffect hook and the getCoordinates function appears to be distinct when printed with console

Utilizing GoogleMap API for Custom Location Display I have an imported array of JSON objects named data which includes an address property. The Google Maps API is used to retrieve coordinates from the addresses in order to generate custom markers displaye ...

Struggling with continuously re-rendering a color background when using useMemo in React?

After every re-render, a new color is generated. Is there a way to store the initial color and reuse it in subsequent renders? const initialColor = generateNewColor(); // some random color const backgroundColor = React.useMemo(() => { return ...

Tips for preventing the error message "The property 'map' is not present on type 'string | string[]'."

I received an error message stating Property 'map' does not exist on type 'string | string[]': const data = [ ['1', ['11']], ['2', ['21']], ['3', ['31']], ] data.map(top ...

Transforming an array of JavaScript objects into arrays of key-value pairs based on a specific property with ES6 syntax

Consider an array of objects like this: myArray = [ {name: 'First', parent: 1, delta: 2}, {name: 'Second', parent: 1, delta: 1}, {name: 'Third', parent: 2, delta: 1} ]; The goal is to transform this array into an objec ...

Issue with updating boolean values in reactive form controls causing functionality to not work as expected

I am currently facing an issue with validating a group of checkboxes. The main problem is that even though the 'this.dataService.minRequired' variable updates in the service, the validation state does not reflect these changes. I initially though ...

Ways to prevent altering values in ngModel

I am working on a component in Angular 5 where I am trying to write unit tests to ensure that when the component is disabled, it should not be possible to set a value to its model. However, even after disabling it, I am still able to change the value. [ ...

The TypeScript alternative to Axios request with native fetch functionality

I have a function that sends a JWT validation request: const sendValidateJWTRequestFetch = (url: string, token: string) => fetch(url, { method: 'GET', mode: 'cors', headers: { Authorization: token, 'Ac ...

Accessing object properties on the fly in TypeScript

I'm currently working on a TypeScript game that features an inventory system with various values, like so: export const Inventory = { food: 0, medicine: 0, rifleAmmo: 0, pistolAmmo: 0 } At the moment, I have a function in place to man ...

Guide to creating a personalized pipe that switches out periods for commas

I currently have a number with decimal points like --> 1.33 My goal is to convert this value so that instead of a dot, a comma is displayed. Initially, I attempted this using a custom pipe but unfortunately, it did not yield the desired result. {{get ...