Is there a way for me to input only the value and have TypeScript automatically determine the key of an object?

My challenge lies in having an object with string keys, but I do not want them to remain as strings. Instead, I desire the keys to be the exact values of the object. This means that I must input the value of the object accordingly to meet certain criteria. Consider the following example,

type ObjectValueType = {
  checked: boolean;
  fields: Path<Camera>[];
};

type ObjectType = Record<string, ObjectValueType>;

const Object: ObjectType = {
  camera_stream_endpoint: {
    checked: false,
    fields: ['camera_stream_endpoint'],
  },
  layout_image: {
    checked: false,
    fields: ['layout_image'],
  },
};

In the above code snippet, a TypeScript type ObjectType is crafted whereby the key is of type string and the value is of type ObjectValueType. My aim is to have the key match the exact keys present in the Object (such as camera_stream_endpoint or layout_image). How can I achieve this key inference?

I am hesitant to resort to creating a union type encompassing all the keys within the object due to its extensive nature. Therefore, I would prefer TypeScript to automatically infer these keys from the created object.

One approach I attempted involved utilizing the assertion as const, like so

const Object = {
  camera_stream_endpoint: {
    checked: false,
    fields: ['camera_stream_endpoint'],
  },
  layout_image: {
    checked: false,
    fields: ['layout_image'],
  },
} as const;

This method successfully achieves the desired outcome for the keys. However, it opens up the possibility for arbitrary values to be inserted. For instance, there could be errors in the fields attribute, which should adhere to the specified type Path<Camera>. TypeScript will not flag any inconsistencies in this scenario.

Ultimately, my goal is to define both the keys and values of the object. The keys should be inferred from the created variable, while the values will possess their individual type definitions. Is such a feat attainable?

Answer №1

If you're looking for a solution, one approach is to derive the keys from your const object, specify the required type, and then assign the const object to a variable with the desired type:

type ObjectValueType = {
  on: boolean;
  options: Path<Device>[];
};

const DeviceConst = {
  device_info: {
    on: false,
    options: ['device_info'],
  },
  sensor_data: {
    on: false,
    options: ['sensor_data'],
  },
};

type DeviceTypes = keyof typeof DeviceConst;

export type CustomDevice = { [key in DeviceTypes]: ObjectValueType };

export const Devices: CustomDevice = DeviceConst;

It's important to note that removing the const assertion is crucial as it can restrict the fields parameter too much for the object to be compatible with the newly defined type.

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

Error in Prisma: Unable to retrieve data due to undefined properties (attempting to access 'findMany')

Recently, I've been working on a dashboard app using Prisma, Next.js, and supabase. Encountering an issue with the EventChart model in schema.prisma, I decided to create a new model called EventAreaChart. However, after migrating and attempting to ex ...

What is the most efficient way to remove all typed characters from fields when clicking on a different radio button? The majority of my fields share the same ngModel on a separate page

Is there a way to automatically clear all typed characters in form fields when switching between radio buttons with the same ngModel on different pages? I noticed that the characters I type in one field are retained when I switch to another radio button. ...

What is the proper method for utilizing a conditional header in an rtk query?

How can I implement conditional header authentication using rtk query? I need to pass headers for all requests except refresh token, where headers should be empty. Is it possible to achieve this by setting a condition or using two separate fetchBaseQuery ...

Angular Form Validations - input values must not match the initial values

These are my current reactive form validations: ngOnInit(): void { this.userForm = this.formBuilder.group({ status: {checked: this.selectedUser.status == 1}, username: [this.selectedUser.username, [Validators.required, Validators.minLeng ...

Utilize a string to access and sort the properties of a class in TypeScript

Let's discuss a simple problem involving objects in Javascript. Take for example an object like this: var obj={ par1:'value1', par2:'value2' } In JavaScript, we can access the values like obj['par1']. Now, the q ...

Submitting information to a server

I have a simple Angular 6 app with follow and unfollow buttons. When you click follow, the number increases. I want to save these follower numbers to a JSON server. Here is the link to the JSON server documentation: JSON Server Documentation To see a dem ...

Obtain the default/initial argument type of typescript for extension purposes

Currently, I am in the process of developing code that automatically generates type hints based on function calls related to GraphQL Nexus tasks. In one of its functions, it requires an anonymous type constructed from the attributes generated automaticall ...

Unable to display grid items in React material-ui grid list

export interface FlatsGridProps { flats: IClusterFlats[]; } export const FlatsGrid: React.StatelessComponent<FlatsGridProps> = (props: FlatsGridProps) => { if (props.flats.length === 0) { return (<div> empty </di ...

Refresh the context whenever the state object changes

Within my application, I am utilizing a PageContext to maintain the state of various User objects stored as an array. Each User object includes a ScheduledPost object that undergoes changes when a user adds a new post. My challenge lies in figuring out how ...

Displaying a dynamic menu using Angular's ngFor loop

I am attempting to create a menu with sub-menus. The desired structure for my menu is outlined below. However, the demo I'm testing is not producing the correct structure. Check out the demo here. "Sub Test": { // Main menu "Example1":"hai",//sub ...

The React Nested Loop Query: Maximizing Efficiency in Data

Learning React has been a challenge for me, especially when comparing it to XML/XPath. In this scenario, I have two arrays simplified with basic string properties... customerList: Customer[] export class Customer { id: string = ""; firstnam ...

What is the reason behind Typescript executing the abstract class before anything else?

I'm currently facing a challenge solving an abstract class problem with Typescript. Let me explain what I am trying to accomplish. There is a class named Sword that extends Weapon. Each Weapon must have certain properties like the damage, but since e ...

Utilizing activatedRoute in Angular to retrieve encoded query parameters

I am facing an issue with my Angular application, where it is loaded after being redirected from another application. I need to access query parameters when the authentication website returns to my Angular application. The URL appears as: http://localhost ...

Having trouble with your Typescript *.ts files?

Having trouble understanding why the command tsc *.ts isn't functioning correctly. The error message TS6053: File '*.ts' not found keeps appearing. Any suggestions on how to compile all the .ts files within a directory? Thank you! ...

Angular 2 allows for duplication of elements using drag and drop functionality

Check out my code on Plunker for drag and drop functionality in drag.ts: http://plnkr.co/edit/PITLKzBB6YXobR1gubOw?p=preview. Please note that it only works in a separate window preview. import {Component, OnInit, ElementRef, Renderer} from '@angular ...

What is the proper type for an object and an array of strings?

We have an array example below. const sampleArray = [ {names: ['example1', 'example2']}, 'another', 'final' ]; Additionally, here is a type error example. The error message reads as follows: "Type 'string ...

The interface is unable to populate the Array of Elements

When using Angular, I send a request and save the response in a variable: conversations: Conversation[]; // ChatService getConversations() { return this.http.get<Conversation[]>('/chat/conversations'); } this.chatService.getConversat ...

Why am I encountering a 400 error with my mutation in Apollo Client, when I have no issues running it in Playground?

After successfully testing a mutation in the playground, I attempted to implement it in my Apollo client on React. However, I encountered an error message stating: Unhandled Rejection (Error): Network error: Response not successful: Received status code 40 ...

Is the "Angular is not functioning" error message the result of a missing import?

Encountering an 'is not a function' error in Angular 7 / TypeScript 3, using an EventEmitter. This issue has been extensively discussed (a b), but solutions have not garnered many upvotes (a b c d e f). I am close to resolving it, but need s ...

Encountered an error while attempting to install the @typescript-eslint/eslint-plugin

After starting the installation process for eslint plugins, I encountered an issue with @typescript-eslint/eslint-plugin. The plugin requires installation using--legacy-peer-deps, but this approach may introduce potential bugs by accepting an incorrect an ...