Using an Enum member as an index for a Record<S,O> type: Is it possible?

When designing a library, I wanted to implement the feature of allowing users to modify its configuration using presets. My approach was to define an Enum containing all possible presets and exporting it with the select function.

Unfortunately, my initial plan did not work out as expected due to some unexpected behavior from the type checker.

The code snippet below showcases the presets and the select method implementation. However, there is an issue where an "illegal" preset is required. Removing this illegal preset (a.1) causes the type checker to complain about Presets lacking an index property. Keeping the illegal preset in the enum requires adding a property to the Presets const with the enum value as the key.

Another complication arises when trying to use the enum for creating the Presets const itself. Uncommenting (b.2) results in everything functioning correctly. However, commenting out (b.1) leads to the type checker flagging an incompatibility error (b.3).

What am I missing here?

export enum Preset
{
    EASY = 'one',
    DEFAULT = 'two',
    HARD = 'three',
    IMPOSSIBLE = 'do_not_use' // (a.1)
}

type Config = Record<'a' | 'b', number>
type PresetNames = Preset.DEFAULT | Preset.EASY | Preset.HARD
type ConfigByPreset = Record<PresetNames, Config>

/* (b.3)
 * [ts] Type '{ [x: string]: { a: number; b: number; }; one: { a: number; b: number; }; two: { a: number; b: nu...' 
 * is not assignable to type 'Record<PresetNames, Record<"a" | "b", number>>'.
 * Property 'three' is missing in type '{ [x: string]: { a: number; b: number; }; one: { a: number; b: number; }; 
 * two: { a: number; b: nu...'.
 */
const Presets: ConfigByPreset = {
    one: { a: 1, b: 101 },
    two: { a: 2, b: 201 },
    ['three']: { a: 3, b: 301 },        // (b.1)
    // [Preset.HARD]: { a: 4, b: 301 }, // (b.2)
}

const defaultConfig = Presets[Preset.DEFAULT]

export function selectPreset( preset: PresetNames ) 
{
    // (a.2) [ts] Element implicitly has an 'any' type because type 'Record<Preset, Record<"a" | "b", number>>' has no index signature.
    const selectedConfig = Presets[preset]
    const otherConfig = Presets['three']

    console.log( 'config = ', selectedConfig, otherConfig, defaultConfig )
}

selectPreset( Preset.EASY )

Answer №1

Titian Cernicova brought to my attention that I had been utilizing an outdated Typescript compiler. It was noted that Eclipse offers the option to use a compiler specific to each project, however, I failed to make the necessary adjustments to the project configuration.

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

When defining a GraphQL Object type in NestJS, an error was encountered: "The schema must have unique type names, but there are multiple types named 'Address'."

Utilizing Nestjs and GraphQL for backend development, encountered an error when defining a model class (code first): Schema must contain uniquely named types but contains multiple types named "Address". Below is the Reader model file example: @ObjectType() ...

Typescript void negation: requiring functions to not return void

How can I ensure a function always returns a value in TypeScript? Due to the fact that void is a subtype of any, I haven't been able to find any generics that successfully exclude void from any. My current workaround looks like this: type NotVoid ...

TypeScript focuses on checking the type of variables rather than their instance

Is there a way to pass a type (not an instance) as a parameter, with the condition that the type must be an extension of a specific base type? For example abstract class Shape { } class Circle extends Shape { } class Rectangle extends Shape { } class ...

Error: The property 'process' cannot be read because it is not defined

Seeking help with a code issue Any advice on best practices would be greatly appreciated. Thank you! An error has occurred: TypeError: Cannot read property 'process' of undefined myComponent.ts ProcessInfo: any | false; showSaveItems = ...

Exploring the wonders of utilizing `instanceof` in TypeScript

Looking at this simple node+ts code: import * as express from "express"; function processRequest(app: express.Application) { if (!(app instanceof express.Application)) throw new TypeError(); // additional logic here... } When I check the code in VSC ...

Encountering a 405 HTTP error in Angular8 app when refreshing the page

Currently, I am working on a project using Angular8 and .NET Core 3.0 in Visual Studio. Everything is running smoothly except for one issue that arises when I press F5 on a page with a form. The error message that pops up reads: Failed to load resource: ...

Is it possible to dynamically change an ngModel value directly from the component?

I'm currently immersed in an Angular project and my initial file setup was like this: dog.ts: export interface Dog { name: string; age: number; breed: string; } dog.component.ts: import { Dog } from '../dog'; @Component({ //setup ...

When using Angular forms, the password or username may be duplicated if entered twice when pressing the

I am currently working on a basic username and password form using Angular. Here's the template I have: <label class="welcome-content">Username:</label> <input #userName type="text" id="txtLoginUsername" (keyup.enter)="loginUser(userNa ...

Typescript: When using ts-node-dev, an error occurred while trying to import express due to an unexpected

I am embarking on a fresh project using Typescript and I intend to set up the node server with typescript utilizing express. There's a helpful tutorial that explains how to execute a Typescript file without going through the hassle of compiling files, ...

What is the process of uploading a file to my Spring Boot-based WebService using an Angular 5 client?

I've put in a lot of effort to solve my issue, but unfortunately, I haven't had any success yet. Currently, I am working with an Angular 5 client and I need to send a file over to my SpringBoot web service so that I can process it on the server ...

What causes a compilation error to occur when a mapped type is invoked inside a class?

Below is a code snippet for review. An error occurs when calling the get method within the class, but works fine when called outside. Any thoughts on why? type DefinedKeys<T> = keyof { [K in keyof T as undefined extends T[K] ? never : K]: K } cla ...

What is the best way to implement ES2023 functionalities in TypeScript?

I'm facing an issue while trying to utilize the ES2023 toReversed() method in TypeScript within my Next.js project. When building, I encounter the following error: Type error: Property 'toReversed' does not exist on type 'Job[]'. ...

Typescript generates a warning when utilizing JSON objects in conjunction with data types

Attempting to access the attributes of a JSON object within a hook using bracket notation. Although it seems to be functioning correctly, TypeScript continues to throw this warning: Property 'github' does not exist on type 'PropertyValues& ...

The absence of a defined HTMLCollection [] is causing an issue

rowGetter = i => { const row = this.state.estimateItemList[i]; const selectRevison = this.state.selectedEstimate.revision; const rowLenght = this.state.estimateItemList.length; const changeColor = document.getElementsByClassName('rd ...

How to best handle dispatching two async thunk actions in Redux Toolkit when using TypeScript?

A recent challenge arose when attempting to utilize two different versions of an API. The approach involved checking for a 404 error with version v2, and if found, falling back to version v1. The plan was to create separate async thunk actions for each ver ...

Trigger the D3 component to re-render in React after a state change occurs in the parent component

My React project consists of two components written in TypeScript. The first component contains menus, and I am using conditional rendering to display different content based on user selection. <Menu.Item name="graph" active={activeItem ...

Handling HTTP errors in Angular when receiving a JSON response

I'm struggling to resolve this issue and I've searched online with no luck. The problem lies in my post call implementation, which looks like this: return this.http.post(url, body, { headers: ConnectFunctions.getHeader() }).pipe( map(result =&g ...

Restrict and ignore associated field in typeorm

I need help in restricting the related data when querying using query builder. Here is the code I have for fetching employee orders: import { getRepository, Repository } from "typeorm"; public async findEmployeeQuery(id : number) { try { ...

Is there a way to display an array of data in separate mat-form-field components?

I am dealing with an array that stores 4 data points: [onHour, onMinute, offHour, offMinute]. I also have 4 elements that are not in an array and need to be repeated. <div class="on"> <mat-form-field appeara ...

Preventing Redundancy in Angular 2: Tips for Avoiding Duplicate Methods

Is there a way I can streamline my if/else statement to avoid code repetition in my header component? Take a look at the example below: export class HeaderMainComponent { logoAlt = 'We Craft beautiful websites'; // Logo alt and title texts @Vie ...