The names of properties in Typescript are determined by the values of the outer type properties

In my project, I have various interfaces (or types) defined as follows:

export type simpleValue = string | number | boolean | Date | null;

export interface Options {
  inline?: OptionsItem[] | unknown[];
  promptField?: string;
  selectedValues?: unknown[];
  valueField?: string;
}

export interface OptionsItem {
  prompt: string;
  value: simpleValue;
}

I am trying to find a solution to assign the values of promptField and valueField to OptionsItem so that they are utilized instead of prompt and value as property names.

Answer №1

In TypeScript, there is no predefined type that functions in this specific manner. Rather, you must create a generic type with parameters corresponding to the literal types of the `promptField` and `valueField` properties. Here's an example:

type OptionsItem<KP extends string, KV extends string> =
  { [P in KP]: string } & { [P in KV]: SimpleValue }

interface Options<KP extends string, KV extends string> {
  inline?: OptionsItem<KP & {}, KV & {}>[] 
  promptField?: KP;
  selectedValues?: unknown[];
  valueField?: KV;
}
   

The `OptionsItem<KP, KV>` type represents an intersection of two mapped types equivalent to `Record<KP, string>` and `Record<KV, SimpleValue>`. It ensures that each object has a `string` property at keys of type `KP` and a `SimpleValue` property at keys of type `KV`.

The `Options<KP, KV>` uses `KP` and `KV` appropriately and also assigns them to the `inline` property. I have excluded `| unknown[]` from the type as it can cause unexpected behavior by making all values `unknown`. Instead, use explicit types for clarity.

I've utilized `OptionsItem<KP & {}, KV & {}>` rather than just `OptionsItem<KP, KV>` to prevent inference issues when checking against `KP` and `KV` inferred from other properties.


If repeatedly specifying type arguments like in the sample object creation seems unnecessary, consider using a generic helper function for type argument inference:

const asOptions =
  <KP extends string = "prompt", KV extends string = "value">(
    o: Options<KP, KV>) => o;

You can now write `const o1 = asOptions({ ... })`, allowing the compiler to infer the type arguments automatically.

This setup provides default values for `KP` and `KV` if they cannot be inferred from the passed object, resulting in clearer code and error detection.

By utilizing such tools, you get both type safety and enhanced developer experience without sacrificing productivity.

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

The HTML file that was typically generated by Webpack is now missing from the output

While working on my nodejs app using typescript, react, and webpack, everything was running smoothly. I was getting the expected output - an HTML file along with the bundle file. However, out of nowhere and without making any changes to my code, I noticed ...

What steps can I take to resolve the "Unable to call a potentially 'undefined' object" error?

I'm currently working with CreateContext in Typescript and I have encountered a problem in the code that I can't seem to resolve. I am trying to use typesafe TX to provide state and dispatch (via useReducer) in a component hierarchy. Here is the ...

Update the form field with today's date in a JHipster application

In our current project in JHipster, we are facing a challenge with setting the default value of a form field as the current date. JHipster offers a moment format for dates, which is essentially an ngbdatepicker. However, when attempting to change the inpu ...

Unable to locate the specified environment variable in the current nest

Currently, I am referring to the official documentation on the NestJs website that provides a guide on using config files: https://docs.nestjs.com/techniques/configuration Below is the code snippet I am working with: app.module import { Module } from &ap ...

Tabulate the number of items in an array based on the month and

I have received JSON data with dates indicating the creation time of multiple parcels. I want to analyze this data and calculate the total number of parcels created in each month. I am new to this process and unsure about which thread on Stack Overflow can ...

Is Typescript pass by value or pass by reference?

I have these files: data.ts: export const myData { info1: "info1", info2: "info2", ... ... } and I also have this class: my-class.ts export class MyClass { private data: any; constructor(data: any) { this.data = data ...

Use the rowTemplate in a Kendo grid without replacing the existing one

I am currently utilizing Angular 1.4 with TypeScript and Kendo UI (employing angular directives). My goal is to create a RowTemplate for each row that dynamically changes the color based on a specific property of the item. While I am aware of jQuery solu ...

Calculate the total values across a row of a work schedule, based on specific conditions

I am facing a challenge with my work schedule data, as it is laid out horizontally. I am trying to calculate the total hours in the schedule based on various criteria such as the person's name, their available hours, shift, and the machine they are as ...

Having trouble processing images in multi-file components with Vue and TypeScript

Recently, I reorganized my component setup by implementing a multi-file structure: src/components/ui/navbar/ Navbar.component.ts navbar.html navbar.scss Within the navbar.html file, there was an issue with a base64-encoded image <img /> ...

Using object in TypeScript to reduce arrays

Is there a way to set the return value for my reducer in TypeScript? I am looking to achieve: Instead of using 'any', what should I assign as the type for acc? How can I define my return type so that the output will be {temp: 60, temp: 60}? retu ...

Limit the typescript generic type to only a singular string literal value, preventing the use of unions

Within my project, I have introduced a generic entity type that utilizes a generic to determine a field type based on a specific set of string literals: type EntityTypes = 'foo' | 'bar' | 'baz'; type EntityMappings = { foo: ...

Troubleshooting issue with Material UI icons in React application with Typescript

I created a set of icons based on a github help page like this: const tableIcons = { Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />), DetailPanel: forwardRef((props, ref) => ( <ChevronRight {...props} ref={ref} /> ...

Changing the state object without using the setState function, but rather utilizing an object method

Utilizing a class within my "useState" hook, with a method to alter its content, here's a concise example: class Example { bar: string; constructor() { this.bar = 'bar'; } changeBar() { this.bar = 'baz ...

Merging an assortment of items based on specific criteria

I have the following TypeScript code snippet: interface Stop { code: string } interface FareZone { name: string; stops: Stop[]; } const outbound: FareZone[] = [{name: 'Zone A', stops: [{ code: 'C00'}] }, {name: 'Zone B ...

Tips for validating Enum Strings using the newest version of Joi?

Is there a way to validate Enum String? In the past, I followed this advice from: https://github.com/hapijs/joi/issues/1449 enum UserRole { Admin = 'admin', Staff = 'staff' } const validator = { create: Joi.object().keys({ ...

Performing a series of HTTP requests within a single @ngrx/effect

I need some guidance as I am new to @ngrx and feeling a bit lost in understanding how it should be used. Let's assume we have an effect named PlaceOrderEffect In this effect, my goal is to handle each request in a specific order. processOrder$ = cre ...

At compile time, Typescript runs smoothly, but errors may arise during runtime

Currently, I am delving into learning Typescript and have encountered a snag in my code. Despite searching extensively for a solution, I have been unable to find any relevant material pertaining to my issue. Below is the code snippet in question: <code ...

"Error: imports are undefined" in the template for HTML5 boilerplate

After setting up an HTML5 Boilerplate project in WebStorm, I navigate to the localhost:8080/myproject/src URL to run it. Within the src folder, there is a js directory structured like this: libraries models place.model.ts place.model.js addr ...

Triggering event within the componentDidUpdate lifecycle method

Here is the code snippet that I am working with: handleValidate = (value: string, e: React.ChangeEvent<HTMLTextAreaElement>) => { const { onValueChange } = this.props; const errorMessage = this.validateJsonSchema(value); if (errorMessage == null ...

Encountered an issue while resolving symbol values statically within my exclusive set of modules

Encountered an error while resolving symbol values statically. The function 'DataModule' is not supported. Consider using a reference to an exported function instead of a function or lambda, resolving the symbol DataModuleRoot in E:/shopify-clien ...