What is the best way to create a generic that can handle readonly types efficiently?

When performing an action on a list

type PerformActionOn<L extends any[]> = L

The approach I am taking is as follows:

const keys = {
  a: ['a', 'b', 'c'] as ['a', 'b', 'c'],
  d: ['d', 'e', 'f'] as ['d', 'e', 'f'],
}

type Keys = typeof keys

type KeysWithAction = {
  [K in keyof Keys]: PerformActionOn<Keys[K]>
}

However, to prevent redundancy (especially with potentially longer lists), I would like to simplify it like this:

const keys = {
  a: ['a', 'b', 'c'] as const,
  d: ['d', 'e', 'f'] as const,
}

type Keys = typeof keys

type PerformActionOn<L extends any[]> = L

type KeyTypes = {
  [K in keyof Keys]: PerformActionOn<Keys[K]>
                                  // ^^^^^^^: Type '{ a: readonly ["a", "b", "c"]; d: readonly ["d", "e", "f"]; }[K]' does not satisfy the constraint 'any[]'.
}

The error arises from attempting to pass a readonly type to PerformActionOn, which expects a generic list type (any[]). Is there a way to specify that PerformActionOn should also accept readonly elements?

Answer №1

Absolutely, the readonly modifier can be used in a generic constraint:

type PerformActionOn<L extends readonly any[]> = L
//                             ^ include this

Alternatively, you can reverse course and eliminate the readonly designation after refining keys using as const:

type Mutable<T> = T extends object ? { -readonly [K in keyof T]: Mutable<T[K]> } : T

Experiment with your types (Playground):

type T1 = Mutable<Keys> // { a: ["a", "b", "c"]; d: ["d", "e", "f"]; }

type KeyTypes = {
    [K in keyof Keys]: PerformActionOn<Mutable<Keys[K]>> // now compiles successfully
}

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

Having trouble with an unexpected value in your Angular2 Service? Don't forget to add

I encountered an error in my Angular2 app: Error: (SystemJS) Unexpected value 'ReleasesService' declared by the module 'AppModule'. Please add a @Pipe/@Directive/@Component annotation. Here is my AppModule code: import { NgModule } fr ...

Dynamic importing fails to locate file without .js extension

I created a small TS app recently. Inside the project, there is a file named en.js with the following content: export default { name: "test" } However, when I attempt to import it, the import does not work as expected: await import("./e ...

The attribute 'tableName' is not found within the 'Model' type

Currently in the process of converting a JavaScript code to TypeScript. Previously, I had a class that was functioning correctly in JS class Model { constructor(input, alias) { this.tableName = input; this.alias = alias; } } Howev ...

What are the steps for integrating TypeScript code into a Vue component?

https://github.com/bradmartin/nativescript-texttospeech This texttospeech package has TypeScript documentation available. Is there a way to convert this code for use in NS-Vue? import { TNSTextToSpeech, SpeakOptions } from 'nativescript-texttospeec ...

Obtain the count of unique key-value pairs represented in an object

I received this response from the server: https://i.stack.imgur.com/TvpTP.png My goal is to obtain the unique key along with its occurrence count in the following format: 0:{"name":"physics 1","count":2} 1:{"name":"chem 1","count":6} I have already rev ...

Exploring the generalization of class member initialization in TypeScript

I am looking to make some modifications to the Blog constructor provided in the "Minimal working example" linked below. The objective is to refactor it using pseudo-code by leveraging a generic ModelHelper class to initialize the members of the "Blog" clas ...

Tips for utilizing chodorowicz / ts-debounce effectively

Looking to utilize the debounce function provided by the ts-debounce package (available at here) in my typescript project. However, struggling to find a concrete example of its usage in typescript. Would greatly appreciate any help or guidance on this ma ...

The TypeScript fs/promises API is experiencing compilation issues when used in JavaScript

While working with TypeScript and the fs/promises API, I encountered an error when compiling and running the TypeScript code. The error message displayed: internal/modules/cjs/loader.js:968 throw err; ^ Error: Cannot find module 'fs/promises' ...

Leveraging AnimatePresence from the Framer Motion library to design an exit animation for a motion.div

My goal is to implement a side menu that smoothly slides in and out when the menu/close button is clicked using framer motion. Initially, clicking on the menu button will cause the menu to slide out from the left side of the screen while changing the butto ...

Improved method for linking two enums with similar appearances

Currently, I use two enums as shown: enum Tab { Approved = "Approved", Pending = "Pending", Sold = "Sold", } enum ProductStatus { Approved = "Approved", Pending = "Pending", Sold = "Sold&q ...

What is the best approach for handling errors in a NestJS service?

const movieData = await this.movieService.getOne(movie_id); if(!movieData){ throw new Error( JSON.stringify({ message:'Error: Movie not found', status:'404' }) ); } const rating = await this.ratingRepository.find( ...

Creating a Blob or ArrayBuffer in Ionic 2 and Cordova: Step-by-Step Guide

Is there a way to generate a blob or an arrayBuffer with TypeScript when using the Camera.getPicture(options) method? I am currently working on an Ionic 2/Cordova project. var options = { quality: 90, destinationType: Camera.DestinationType.FILE_ ...

Error message "The result of this line of code is [object Object] when

Recently, I encountered an issue while retrieving an object named userInfo from localStorage in my Angular application. Despite successfully storing the data with localStorage.setItem(), I faced a problem when attempting to retrieve it using localStorage.g ...

What is the best way to exclude a particular subtype or property?

Is there a way to exclude a specific nested property? Let's take a look at an example. interface ILikes { article: string, page: string, userId: number | string, } interface IUserData { userName: string, isAdmin: boolean, ...data, ...

Exploring the power of RxJs through chaining observers

In my Angular application, I am utilizing Observables to set up a WebSocket service. Currently, I have the following implementation: readwrite(commands: command[]) : Observable<response[]>{ const observable = new Observable((observer)=>{ ...

Issue with Angular 6: Textarea displaying value as Object Object

I have data saved in local storage using JSON.stringify, and I want to display it in a textarea. Here are the relevant code snippets: { "name": "some name" } To retrieve the data, I'm using this: this.mydata = localStorage.getItem('mydata&a ...

Navigating through different components in Angular 4 using a service for routing

Encountering an issue while connecting my Angular 4 and REST application with a service. Here's the error message: compiler.es5.js:1694 Uncaught Error: Can't resolve all parameters for TypeaheadComponent: (?, [object Object], [object Object]). ...

Get the dynamic type as the return value in a TypeScript abstract class method with generic type T

Within my codebase, I have created an abstract class: export abstract class Filters<P> { protected field: string; protected constructor(field: string) { this.field = field; } protected abstract getFilter(): P; } Additionally, there is ...

Utilizing TypeScript generics to accurately extract type information from state during reduction

In the context of a state reducer presented as follows: const anObject = { fruit: 'Apple', today: new Date(), } function reducer(state, stateReducer) { return stateReducer(state); } const fruit = reducer(anObject, state => state.fruit ...

Exploring Aurelia's Integration with ASP.NET Core Models

Recently, I've been delving into various JavaScript frameworks and made the decision to rework an ASP.Net Core MVC frontend using Aurelia. To kick things off, I utilized the SPA template. Everything has been smooth sailing so far - I’ve integrated ...