Creating Typescript types from object keys and arrays of string values

I want to create a type based on an Object's keys and values, which are arrays of strings. This type should include all the possible string values like so:

const Actions = {
  foo: ['bar', 'baz'],
}

# type generated from Actions should be:
type ActionsType = 'foo' | 'bar' | 'baz'

I have to keep Actions as it needs to be passed to a method, therefore:

const Actions = {
  foo: ['bar', 'baz'],
} as const


type ActionsType = keyof typeof Actions | typeof Actions[keyof typeof Actions][number]

Although generating the type correctly prevented me from passing Actions to a method that expects Record<string, string[]> because the keys and values became readonly.

Is there a way to generate the necessary type while still being able to use Actions as a non-readonly Object?

Answer №1

Looking for a simple way to make readonly values mutable again after using const assertions / as const? Check out this solution:

type Mutable<T> = {-readonly [K in keyof T]: Mutable<T[K]>}
You can apply this with a type assertion and maintain type safety, like so:
type T1 = Mutable<typeof Actions> // { foo: ["bar", "baz"]; }

function foo(a: Record<string, string[]>) {}
foo(Actions as Mutable<typeof Actions>) // it works

Note that the Actions object could potentially be mutated within the foo function, necessitating a treatment as mutable in the parent module as well. An alternative approach would be adjusting the foo function signature to accept readonly arrays:

function foo2(a: Record<string, readonly string[]>) {}
foo2(Actions) // no need for type assertion here

Try this out in action with this interactive demo

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

Utilize a fusion of various subjects and observables

I have the below code snippet: readonly todos$: Observable<Todo[]> = combineLatest([this.account$, this.loadTodoPage$]).pipe( concatMap(([account, pageNo]) => this.todoService.getTodos(account.id, pageNo)), scan((acc: Todo[], curr: Todo[ ...

``In search of a solution: Resolving the Error Message "Dropzone already attached

Whenever I try to upload an image successfully, I need to execute the editDataImage() function in order to fetch the data stored on the server. However, I encounter an error when attempting to display the image data in the dropzone. Any assistance would be ...

Angular // binding innerHTML data

I'm having trouble setting up a dynamic table where one of the cells needs to contain a progress bar. I attempted using innerHTML for this, but it's not working as expected. Any suggestions on how to approach this? Here is a snippet from my dash ...

Dynamically setting the height of elements using jQuery with incremental values

My Objective: I am trying to dynamically adjust the height of each li element within a ul.container. The goal is to find the tallest li, add 25px to its height, and then apply that new height to all other li elements in the container. This calculation ne ...

Utilize context.isPointInPath(x, y) in HTML5 Canvas for intricate shapes that contain multiple paths

I am currently working on a project that involves drawing a complex shape composed of 6 thin lines and two thick lines. In my code, I have defined 8 paths to achieve this: context.save(); context.lineWidth=2; var TAB_ABSTAND=10; var T ...

Would it be expected for these two JQuery functions to exhibit identical behaviors?

If I have the following two JQuery functions - The first one is functional: $("#myLink_931").click(function () { $(".931").toggle(); }); The second one, however, does not work as expected: $("#myLink_931").click(function () { var class_name = $(thi ...

What is the process for generating an index.d.ts file within a yarn package?

I'm facing an issue with creating the index.d.ts file for my yarn package. Here is my configuration in tsconfig.json: { "include": ["src/**/*"], "exclude": ["node_modules", "**/*.spec.ts"], " ...

What is the process for transmitting information via a Link in Next.js?

In my upcoming 13.1.5 version, I am faced with a challenge of sending the value of contact.name through a Link in my component. I am looking for the most effective approach to achieve this. The initial code block for the Link represents my original code. ...

When altering the color of a mesh in Three.js, only a single face is impacted by the modification

I have a GLB model with multiple parts and hierarchy. My goal is to highlight a specific part of the assembly on mouseover. The code snippet I am using for this functionality is as follows: raycaster.setFromCamera( pointer, camera ); ...

When using NestJS and Serverless, the error message "handler 'handler' is not a function" may be encountered

Currently, I am in the process of incorporating NestJS as an AWS Serverless function using serverless-framework. Following the official documentation, my code mirrors that of the documentation. However, upon launching it, I encounter the error message Fai ...

Charts are not displaying properly in Angular 10 when using ng2-charts

My application is supposed to display charts, but for some reason, the charts are not loading. When I check the DOM, I see the element being created with ==$0, which is confusing to me. I am using Angular Material, but I don't think that should be a ...

Is there a way to switch out the ionic2-super-tabs Toolbar for the ion-slides pager feature?

Hello there, Currently, I am utilizing the following plugin in my Ionic 3 project: https://github.com/zyra/ionic2-super-tabs The plugin offers a great functionality for swipeable tabs in Ionic applications. In its documentation, it demonstrates how to hi ...

Following the execution of the commit, the variable remains in a state of

I'm currently in the process of creating a new task. I was expecting the result to be 'created task with title', but the title is empty because 'formData' is still reactive. Below is an example of the code: // index.vue <form ...

Determine the figures derived from a pair of input fields utilizing jQuery

I'm attempting to combine the scores from Level 1 and Level 2 and showcase the result within the <div id="score"></div>. So far, this is what I've come up with, but it doesn't work for all inputs and seems like a convoluted mess ...

What is the best way to assign multiple events and handlers using the .on method?

I've been attempting to move a submenu using multiple handlers within the on method. My goal is to trigger the function panelON when the mouse enters one of the li elements, and execute the function panelOFF when the mouse leaves it. I have tried dif ...

Unable to make a reference to this in TypeScript

In my Angular2 application, I have a file upload feature that sends files as byte arrays to a web service. To create the byte array, I am using a FileReader with an onload event. However, I am encountering an issue where I cannot reference my uploadService ...

Technique for transferring information between properties of a class instance within an Express server's architecture

I am in the process of developing a monitoring server for a library using Express. My goal is to create different routers and routes, while also being able to access functions and variables from the monitor-server class. Currently, I have passed the ' ...

Issue with ESLint error in TypeScript PrimeReact async Button click handler

I am currently facing an issue with exporting data from a DataTable in PrimeReact. The onClick function for the Button does not allow async callbacks as flagged by eslint. Can someone guide me on how to properly call this function? const exportCSV = us ...

Trouble with comparing two datetime values in JavaScript

I have a dilemma with two different appointments: appointment1 = "2013-07-08 12:30:00" appointment2 = "2013-07-08 13:30:00" My goal in JavaScript is to compare these two appointment dates. If they don't match, I want to remove the appointment; if t ...

What could be causing the `unstable_Profiler` to not function properly in production mode?

Encountering a problem with unstable_Profiler in my React-Native project where the onRender callback is being ignored, but only in production mode. No errors are being thrown and everything renders correctly. I followed the advice from this article: I tes ...