Determine parameter types and return values by analyzing the generic interface

I am currently working on a feature where I need to create a function that takes an interface as input and automatically determines the return types based on the 'key' provided in the options object passed to the function.

Here is an example of what I'm aiming for:

const stringKeyValue = createKeyValueMapped<{a: string, b: number}>({
 key: "a", // key: "a"
 value: "hi",  // value: string
 transform: (value) => value + ' more text', // (value: string) => string
}); 

stringKeyValue.key;  // key: 'a'
stringKeyValue.value; // value: string 

The problem is that in my current implementation, the key type ends up being 'a' | 'b', and the value type becomes 'string' | 'number'.

This is the existing code snippet causing issues:

export type KeyValue<
  Inputs,
  Key extends keyof Inputs,
  Value = Inputs[Key]
> = {
  key: Key;
  value: Value;
  transform: (value: Value) => Value;
};

type KeyValuesMapped<Inputs> = {
  [Key in keyof Inputs]: KeyValue<Inputs, Key>;
}[keyof Inputs];

const createKeyValueMapped = <Inputs,>({ key, value }: KeyValuesMapped<Inputs>) =>
  ({
    key,
    value,
  });

I attempted to solve this by creating a type for KeyValue, encapsulating the options within a function, and specifying the return types. However, this approach completely broke the mapping functionality.

You can explore a comprehensive example using this Link to Playground

Answer №1

At this time, the key property lacks generality. The function remains unaware of and indifferent towards the value you provide for it. Consequently, the output type cannot vary based on the key.


An apparent resolution would involve introducing a generic type for the key.

const createKeyValueMapped = <
  Inputs, 
  K extends keyof Inputs
>({ key, value }: KeyValue<Inputs, K>) =>
  ({
    key,
    value,
  });

The caller must explicitly define the key when invoking the function as TypeScript currently does not support partial type inference.

const stringKeyValue = createKeyValueMapped<CustomInputs, "a">({
  key: "a",
  value: "hi",
  transform: (value) => value + ' more text',
});

To eliminate the need for setting the second generic type manually, currying can be utilized.

const createKeyValueMapped = <Inputs,>() =>
  <K extends keyof Inputs>({key, value}: KeyValue<Inputs, K>) => ({
    key,
    value,
  });

const stringKeyValue = createKeyValueMapped<CustomInputs>()({
  key: "a",
  value: "hi",
  transform: (value) => value + ' more text',
});

In this scenario, the outer function takes an explicit generic type while the inner function deduces the key.

stringKeyValue.key; // "a"
stringKeyValue.value; // string

Interactive Code Playground

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 difficulty integrating requireJS and Node's Require in a single TypeScript project

I currently have a TypeScript project that is intended to work with both Node and the browser. In some scripts, I'm utilizing Node's require(), while in others requireJS's require(). The structure of my project directory is as follows: myPr ...

The configuration of the property has not been declared (Error: <spyOnProperty>)

Imagine having a MenuComponent @Component({ selector: 'cg-menu', templateUrl: './menu.component.html', styleUrls: [ './menu.component.scss' ] }) export class MenuComponent implements OnInit { menu: MenuItem[]; isLog ...

Resolving TypeScript error when importing images statically in Next.js

In order to enhance the performance of images in my nextjs app, I am working on image optimization. However, I encountered an issue stating: Cannot find module '/images/homeBg.jpg' or its corresponding type declarations. The image is actually st ...

What is the best way to structure a nested object model in Angular?

Issue occurred when trying to assign the this.model.teamMembersDto.roleDto to teamMembersDto. The error message states that the property roleDto does not exist on type TeamMembersDropdownDto[], even though it is nested under teamMembersDto. If you look at ...

Converting a string[] to an EventEmitter string[] in Angular 4 with TypeScript: Step-by-step guide

Programming Language: Typescript – written as .ts files Development Framework: Angular 4 I'm currently working on an application that is supposed to add chips (similar to tags in Angular 1) whenever a user types something into the input box and hi ...

Node Express and Typescript app are failing to execute new endpoints

Hello, I'm currently diving into Node express and working on a simple CRUD app for pets. So far, I've successfully created 2 endpoints that are functioning properly. However, whenever I try to add a new endpoint, Postman fails to recognize it, g ...

Encountering difficulty when determining the total cost in the shopping cart

I am currently working on a basic shopping cart application and I am facing an issue when users add multiple quantities of the same product. The total is not being calculated correctly. Here is my current logic: Data structure for Products, product = { ...

"Encountering an issue with mounting components in React Unit Testing with Jest and Typescript

Having developed a simple app with components, here is the code: import GraphicCanvas from './Graphing/GraphCanvas'; import { drawCircle } from './Graphing/DrawCircle'; function App() { return ( <div className="App"&g ...

Utilizing Generic Types for Object Parameters

Why am I encountering an error when trying to use a function of type A for a B type one? How can I define a function type with unknown properties? When I attempt to define props in type B as props: Record<string, unknown>, it results in a similar err ...

Tips for effectively managing 404 errors in Angular 10 with modular routing

I'm facing challenges with handling 404 pages within an Angular 10 application that utilizes modular routing architecture. Here is the structure of my code: |> app |-- app.module.ts |-- app-routing.module.ts |-- app.component{ts, spec.ts, scss, ht ...

Error encountered when attempting to assign a value of the original data type within the Array.reduce function

I am in the process of developing a function that takes a boolean indicator object like this: const fruits = { apple: false, banana: false, orange: false, mango: false, }; Along with an array such as ['apple', 'orange']. The go ...

Exploring the new possibilities of Angular 5: Enhanced REST API service with paginated data and object mapping capabilities

After implementing pagination in my REST API backend, I now need to update my Angular services to accommodate the changes. Instead of simply returning an array of objects, the API will now return JSON responses structured like this: { "count": 0, ...

Building Silent Authentication in React Native with the help of Auth0: A Step-by-Step Guide

I am currently working on my first React Native app, and I have integrated Auth0 for authentication purposes. My goal is to implement silent authentication using refresh tokens. So far, I have attempted to use the checkSession() method but encountered an ...

Using react-confetti to create numerous confetti effects simultaneously on a single webpage

I'm looking to showcase multiple confetti effects using the react-confetti library on a single page. However, every attempt to do so in my component seems to only display the confetti effect on the last element, rather than all of them. The canvas fo ...

The challenge with the Optional Chaining operator in Typescript 3.7@beta

When attempting to utilize the Typescript optional chaining operator, I encountered the following exception: index.ts:6:1 - error TS2779: The left-hand side of an assignment expression may not be an optional property access. Here is my sample code: const ...

The React-Typescript error message is stating that the module "react-router-dom" does not have the exported member "RouteComponentProps"

I encountered an issue with my project involving a login page and the usage of "RouteComponentProps". Unfortunately, I received the following error: Module '"react-router-dom"' has no exported member 'RouteComponentProps'. Upon attempt ...

Ways to modify the input field value in my form based on the current page context

I am currently developing a website for a sports event organization company using Angular, HTML/CSS. The focus of this website is on the triathlon sport and it consists of several stages. On the home page, there are five image tags representing each stage ...

Updating color of an element in SVG and Angular2+ according to the background

In my svg element, I have a text element positioned after two rect elements. <svg id="floor-plan" width="300" height="100"> <rect width="300" height="100" fill="white"/> <rect width="50" height="50" fill="green"/> <text x="10" y="10" ...

Associating function parameters with object types in TypeScript

In the conclusion of this post, I provide operational code for associating object types with a function that accepts an object containing matching properties. The code snippet I shared results in 'result' being resolved as: type result = { GE ...

Angular Update Component on Input ChangeEnsuring that the component is automatically

<div class=" card-body"> <div class="row"> <div class=" font-icon-list col-lg-2 col-md-3 col-sm-4 col-xs-6 col-xs-6" routerLinkActive="active" *ngFor="let subject of subjects"> <div class=" fon ...