Find the appropriate return type for a TypeScript function based on its argument

Is it feasible in TypeScript to infer the return type of a function based on its arguments? This feature would be beneficial when extracting specific properties from, for example, a database query.

Here is an illustration (https://repl.it/repls/IrresponsibleUnsightlySequences#index.ts) :

type QueryReturnType = {
  a: string;
  b: number;
  c: boolean;
};

const queryFunc = (): QueryReturnType => {
  return {
    a: 'b',
    b: 1,
    c: true,
  };
};

type Params = {
  [key: string]: keyof QueryReturnType;
};

const takeQuerySubset = (params: Params) => {
  const res: any = {};
  Object.keys(params).map((key) => {
    res[`${key}`] = queryFunc()[params[key]];
  });

  return res;
};

takeQuerySubset({ test1: 'a' }); // { test1: 'b' }

takeQuerySubset({ test2: 'b' }); // { test2: '1' }

takeQuerySubset({ test3: 'b', test4: 'c' }); // { test3: '1', test4: true }

Although the current implementation works, the type of takeQuerySubset is: (params: Params) => any, whereas the objective is to derive a return type dynamically based on the parameters i.e.:

takeQuerySubset({ test1: 'a' }); // should return {test1: string}

takeQuerySubset({ test2: 'b' }); // should return {test2: number}

takeQuerySubset({ test3: 'b', test4: 'c' }) // should return {test3: number, test4: boolean}

This approach ensures that another function utilizing takeQuerySubset can accurately predict the output received.

I attempted using generics to replace any without success. Additionally, note that variables have been renamed e.g. a is now referred to as test1, b as test2, etc.

Answer №1

Utilizing generics in TypeScript allows for flexibility up to a certain extent, as outlined in the documentation available at this link. Alternatively, one can also leverage intersection and union types by referring to this resource. For instance, you can create a type that encompasses both number and string (union type). However, this approach may lead to ambiguity regarding the exact return type of your function for the caller, prompting the need to implement a type guard.

Answer №2

It seems like what you are looking for is this solution:

function extractSubsetFromQuery<T extends Record<string, any>>(params: T): T {
  const result: any = {};
  Object.keys(params).map((key) => {
    result[`${key}`] = fetchData()[params[key]];
  });

  return result;
};

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

What are the steps for designing personalized syncfusion grid-columns while still preserving the built-in search functionality of syncfusion?

Looking to transform the data coming from the backend, specifically mapping a user's status which is represented as a number to its corresponding string value. Considered using typescript for this mapping task, but it interferes with syncfusion' ...

Can you please provide an explanation on the functioning of Dependency Injection in Nestjs?

I have been delving into Nest.js and incorporating it into my project structure. Additionally, I have integrated TypeORM into the mix. The concept of Dependency Injection in Nest.js has me feeling a bit perplexed. Project Structure |-APP_MODULE |-app.co ...

Tips for automatically creating a categoryId using ObjectId for a category in Nest JS, Typescript, and Mongoose

book.entity.ts import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; import mongoose, { Document } from 'mongoose'; import { Category } from 'src/category/entities/category.entity'; export type BookDocument = Book & ...

Display the initial x list items without utilizing ngFor in Angular 2

In the template, there are 9 <li> elements, each with a *ngIf condition present. It is possible that 5 or more of them may return true, but the requirement is to only display the first 4 or less if needed. Priority is given to the order of the < ...

Can you identify the TypeScript type for an array containing various Angular components?

In my application, I have a diverse range of components that I would like to organize into an array. There are no restrictions on what types of components can be included in this array, as long as they are Angular components. What is the correct way to de ...

How to utilize *ngFor alongside the async pipe for conditional rendering in Angular 8 HTML

.html <ng-container *ngFor="let contact of listContact | async; let index = index;"> <h6 class="title" *ngIf="contact && contact['type']"> {{contact['type']}} </h6> <div> {{conta ...

Using Material UI date picker with TypeScript: A Complete Guide

Well, I have to admit that I usually don't resort to putting 'any' as the type when I'm uncertain what to do, but right now, I'm starting to feel quite frustrated. I'm currently working with Material UI date picker in conjunct ...

The new update of ag-grid, version 18.1, no longer includes the feature for enabling cell text selection

I am attempting to disable the clipboard service in ag-grid. I have come across the enableCellTextSelection flag, which supposedly disables it completely. However, when I try to use this flag as a direct property of <ag-grid-angular>, it results in a ...

If placed in the same document, will promises be executed sequentially?

Let's say I have a function in one file that returns a promise: public async a():Promise<string>{ return 'hi' } In another file, I use this function like so: await service.a.then( hi =>console.log(hi)).catch(err=>{throw err}); ...

Angular 6 - The state of the expression was altered after it was verified, different types of constructions

During the build process in debug mode with ng build, I am encountering errors in some components. However, when I switch to production mode using ng build --prod, these errors disappear. I am curious as to why this discrepancy is occurring. Error: Expre ...

Discover the initial item in Observable that meets a certain criteria

I am trying to retrieve the first item of type avatar from payload.result within an observable: let result = this.fileService.getAvatarByUserId(2).pipe( map((payload: Payload<FileModel[]>) => payload.result), first((result: FileModel[]) => ...

Utilize ngClass for every individual section

I have completed the implementation of all UI components, which are visually appealing. Here is the data structure I am using: public filters = [ { tag: 'Year', label: 'year', items: [200 ...

Transmitting Filter Choices as an Object for Retrieving Multiple Values within an Angular Application

In my Angular application, I have a function that takes user selections for various filter types and sends a request to the API to retrieve filtered data based on those selections. Each filter type returns values in an array format, allowing users to selec ...

How is it possible to access a variable in a function that hasn't been declared until later?

While working on a Dialog component, I had an unexpected realization. export const alert = (content: string) => { const buttons = [<button onClick={()=>closeModal()}>ok</button>] // seems alright // const buttons = [<button onCli ...

What is the best way to eliminate a particular element from an array produced using the .map() function in

I am experiencing an issue with my EventCell.tsx component. When a user clicks on the component, an event is created by adding an element to the components state. Subsequently, a list of Event.tsx components is rendered using the .map() method. The problem ...

Compilation in TypeScript taking longer than 12 seconds

Is anyone else experiencing slow TypeScript compilation times when building an Angular 2 app with webpack and TypeScript? My build process takes around 12 seconds, which seems excessively slow due to the TypeScript compilation. I've tried using both ...

Modifying data types within complex nested object structures

I am looking to traverse the data structure recursively and create a custom type with specific fields changed to a different type based on a condition. Using the example structure below, I aim to generate a type (Result) where all instances of A are repla ...

Automatically adjust padding in nested lists with ReactJS and MaterialUI v1

How can I automatically add padding to nested lists that may vary in depth due to recursion? Currently, my output looks like this: https://i.stack.imgur.com/6anY9.png: However, I would like it to look like this instead: https://i.stack.imgur.com/dgSPB. ...

Oops, it seems like there was an issue with NextJS 13 Error. The createContext functionality can only be used in Client Components. To resolve this, simply add the "use client" directive at the

**Issue: The error states that createContext only works in Client Components and suggests adding the "use client" directive at the top of the file to resolve it. Can you explain why this error is occurring? // layout.tsx import Layout from "./componen ...

What is the process for extracting dates in JavaScript?

I need help extracting the proper date value from a long date string. Here is the initial date: Sun Aug 30 2020 00:00:00 GMT+0200 (Central European Summer Time) How can I parse this date to: 2020-08-30? Additionally, I have another scenario: Tue Aug 25 ...