An item where the value of one key is determined by the value of another key

How can we implement this specific pattern in code (please note that this is not valid syntax and should be considered pseudocode):

type Config = {
  [key: string]: <T> {
    params: T,
    doSth: (params: T) => void,
  },
}

In this scenario, the generic type T is unique for each key's value within the object, but it is also reused under different fields within the same value. Additionally, the T type is derived from the params field. This setup allows for:

const config: Config = {
  a: {
    params: { x: 123 },
    doSth: params => {}, // The type of "params" would be "{ x: 123 }"
  },
  b: {
    params: { y: 'asd' },
    doSth: params => {}, // The type of "params" would be "{ y: 'asd' }"
  },
}

Surprisingly, searching for similar implementations or solutions to this problem did not yield relevant results. It appears to be a useful pattern with no direct matches in existing resources. Previous attempts to adapt solutions of similar problems have been unsuccessful.

Answer №1

When working with TypeScript, sometimes types alone are not enough to achieve the desired outcome, and you may need to use functions for assistance, even if they do not have a runtime impact. This scenario calls for a different approach. Here is a function that demonstrates this concept:

type ConfigEntry<T extends object> = {
    params: T;
    doSth: (params: T) => void;
};

function createConfigEntry<T extends object>(obj: ConfigEntry<T>): ConfigEntry<T> {
    return obj;
}

The ConfigEntry type allows us to connect the two instances where this type will be utilized. The usage of this function can be seen when assigning property values:

const configuration = {
    optionA: createConfigEntry({
        params: { x: 123 },
        doSth: params => {}, // Type of `params` is `{ x: number; }`
    }),
    optionB: createConfigEntry({
        params: { y: "asd" },
        doSth: params => {}, // Type of `param`s is `{ y: string; }`
    }),
};

Please note that there is no explicit type annotation for configuration. TypeScript infers it from the object initialization.

However, the types inferred on params might not align exactly with your requirements. TypeScript does not automatically deduce the types as expected. It will either infer { x: number; } and { y: string; }, or when defining the objects as const, it will infer { readonly x: 123; } and { readonly y: "asd"; }:

const configuration = {
    optionA: createConfigEntry({
        params: { x: 123 } as const,
        doSth: params => {}, // Type of `params` is `{ readonly x: 123; }`
    }),
    optionB: createConfigEntry({
        params: { y: "asd" } as const,
        doSth: params => {}, // Type of `params` is `{ readonly y: "asd"; }`
    }),
};

This might not match your exact specifications, but it gets pretty close. It showcases one of the possible approaches using current TypeScript capabilities.

Playground example for reference

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

Utilizing ag-grid with Vue.js: Implementing TypeScript to access parent grid methods within a renderer

I've integrated ag-grid into my project and added a custom cell renderer: https://www.ag-grid.com/javascript-grid-cell-rendering-components/#example-rendering-using-vuejs-components Although the renderer is working well, I'm facing an issue whe ...

Troubleshooting the creation of migration paths in NestJS with TypeORM

After diligently studying the NestJS and TypeORM documentation, I have reached a point where I need to start generating migrations. While the migration itself is creating the correct queries, it is not being generated in the desired location. Currently, m ...

"Strange Type Conversion Behavior in next.js 13: Why is res.json() Converting Numbers to Strings

I have encountered a strange issue where no matter what I do, the fetched data is being partially converted to strings. For example, the 'bialko' and 'kcal' fields are supposed to be of type Float in Prisma, yet they are getting casted ...

Transferring HTML attributes from an Immutable object in Typescript

This implementation is effective type Props = DR<IBtnWrapperPropsBasic> & {otherbuttonProps?: ButtonHTMLAttributes<HTMLButtonElement>} class Btn extends Component<Props, {}> { ... public render() { const {handleCl ...

Referring to a component type causes a cycle of dependencies

I have a unique situation where I am using a single service to open multiple dialogs, some of which can trigger other dialogs through the same service. The dynamic dialog service from PrimeNg is being used to open a dialog component by Type<any>. Ho ...

Accessing a property that doesn't exist on a union type in Phaser using TypeScript

Currently, I've been immersed in the world of game development with Phaser 3 by following this insightful tutorial at . However, my focus has now shifted towards deploying these games online and adapting the code for use with TypeScript while gearing ...

Syntax for nested arrow functions in TypeScript

const fetchAsyncData = (input: { value: string }): AppThunk => async (dispatch) => { try { const fetchedData = await getData({ input.value }); } catch (error) { console.log(error); } }; An error message is displayed stating "No value ...

How to retrieve a specific property from an array within an object using Typescript

I'm currently working on accessing information from a blog using Typescript. I'm having trouble figuring out how to access the title item since it is within an array. export default function Post({list}: Props) { console.log(" ...

Creating an object efficiently by defining a pattern

As a newcomer to Typescript (and Javascript), I've been experimenting with classes. My goal is to create an object that can be filled with similar entries while maintaining type safety in a concise manner. Here is the code snippet I came up with: le ...

Exploring the traversal of an array of objects within Tree Node

How can I transform my data into a specific Tree Node format? Is there a method (using Typescript or jQuery) to iterate through each object and its nested children, grandchildren, and so on, and modify the structure? Current data format { "content" ...

Exploring the process of dynamically incorporating headers into requests within react-admin

Currently utilizing react-admin with a data provider of simpleRestProvider. I am in need of a solution to dynamically add headers to requests based on user interactions. Is there a way to achieve this? Appreciate any assistance. Thank you! ...

Integration of a JavaScript file with an Angular 4 project: Steps to import the file and leverage its functions within a component

I'm having trouble importing the openseadragon.min.js file into my index.html and utilizing its functions as shown below: var viewer = OpenSeadragon({ id: "seadragon-viewer" }); Unfortunately, I'm receiving an error stating that OpenSeadragon ...

Validate the button's status in Ionic

When I click on a button, I am trying to retrieve the Toggle state immediately. However, I consistently receive a value of true, even when my toggle is actually set to false. I believe the issue lies in how I am manipulating the DOM. Here is an example ...

Finding a way to reference multiple components within a mapping function

In order to set a ref to each project within the map function, I am trying to pass forwardRef from child to parent. At the moment, I am only able to get a single Project. However, I need to set refs to an array list so I can work with it. Below is what I h ...

What steps should I take to resolve the ChunkLoadError related to signalr?

Recently, I encountered an issue while running my nx site locally. It seems that any federated app using signalR is now throwing a ChunkLoadError. I attempted various solutions such as changing the version of signalR, reloading the page, clearing cache, a ...

What is the best way to check the API response status in NextJS13?

Currently, I am experimenting with different methods to handle API HTTP status in my NextJS-13 project but so far nothing has been successful. Note: TypeScript is being used in this project. Below is my code snippet with a static 200 API response and the ...

What is the method to ensure that the children of an object strictly adhere to a specific interface or inherit from it?

Is there a way to ensure that an interface extends from another interface in TypeScript? For example: export interface Configuration { pages: { home: IHome; about: IAbout; // How can we make IAbout extend IPage? contact: IPage; }; } inte ...

Error: The function of splitting 'a' is not available within the context of 'r' (angular.js:263

Although I comprehend the error message, I have not implemented any split functions in my application. The error seems to be originating from the angular.js file itself and is something that has only surfaced recently. I am curious to know if anyone else i ...

NestJs Function yielding inconsistent results based on its calling location

There is a puzzling issue that I am unable to solve. I have stored priceHistories in memory within an array. Strangely, when I invoke a get method, the returned value varies depending on where the method is called from. This is the original property and m ...

The ng-template directive does not duplicate data, whereas HTML elements have the ability to showcase it

When trying to display JSON data using ng-template, I am facing issues as the data is not showing up. However, if I use HTML elements like div or span, it displays correctly. JSON format: const arr = [ { "date": 1, "color": "n ...