Can one utilize generic parameter value within a conditional type result field in Typescript?

Trying to create a versatile function type for data transformation can be a bit tricky. When dealing with a single object, it's straightforward:

export type SingleObjFunction<InputDataType, OutputDataType> =
  (object: InputDataType) => OutputDataType;

However, when working with an array of objects, I want the function to return either an object with a field: OutputDataType[] property inside, or just a plain array. Is it possible to achieve this flexibility by using another generic parameter like so:

export type MultipleObjFunction<
  InputDataType, 
  OutputDataType, 
  InnerField extends (string | undefined), 
  FunctionResult = InnerField extends string
    ? { [Key in InnerField]: OutputDataType[] }
    : OutputDataType[]
> = (objs: InputDataType[]) => FunctionResult

I am aware that there is no direct equivalent to valueof, but perhaps there is an alternative approach?

Answer №1

To create the type parameter FunctionResult for your function, you can leverage a mix of default type parameters and conditional types. This approach allows the compiler to determine the return type based on the resolved type of the InnerField parameter.

If the resolved type of InnerField is assignable to string, the function will return an object type

Record<InnerField, OutputDataType[]>
. Otherwise, it will return an array type OutputDataType[].

For further exploration and testing, check out this TS Playground link.

type MultipleObjFunction<
  InputDataType, 
  OutputDataType, 
  InnerField extends (string | undefined) = undefined,
  FunctionResult = InnerField extends string
    ? Record<InnerField, OutputDataType[]>
    : OutputDataType[]
> = (objs: InputDataType[]) => FunctionResult;

type In = {
  str: string;
  num: number;
};

type Out = { result: string };

declare const arg: In;

declare const f1: MultipleObjFunction<In, Out>;
const r1 = f1([arg]);
    //^? const r1: Out[]

declare const f2: MultipleObjFunction<In, Out, 'myPropertyName'>;
const r2 = f2([arg]);
    //^? const r2: Record<"myPropertyName", Out[]>
type R2Key = keyof typeof r2;
   //^? type R2Key = "myPropertyName"
r2.myPropertyName
 //^? (property) myPropertyName: Out[]

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

Creating a React Typescript interface with nested interfaces for props

My issue is with a functional component that is supposed to receive props from another functional component. The problem lies in the fact that an interface within the receiving component always returns 'undefined' when I log it in the console. De ...

How to define a TypeScript recursive object with a defined endpoint?

Welcome to my first question! I am currently facing an issue with defining an object to store strings in multiple languages. I am looking for a flexible solution and have considered using a nested object structure. However, I want the final object to adhe ...

Issue with TranslateModule Configuration malfunctioning

I have put together a file specifically for managing ngx-translate configuration: import { Http } from '@angular/http'; import { TranslateHttpLoader } from '@ngx-translate/http-loader'; import { TranslateLoader, TranslateModu ...

Validating mixed types and generics within an array using Typescript's type checking

I am currently working with a setup that involves defining interfaces for animals and their noises, along with classes for specific animals like dogs and cats. I am also storing these animals in an array named pets. interface Animal<T> { name: stri ...

"Implementing a unique constraint in Drizzle-orm PostgreSQL with the additional condition of deleted_at being

Is there a way to construct a table using a WHEN SQL tag? I am interested in setting up a table similar to this: "members_table", { id: serial("id").primaryKey(), email: text("email").notNull(), team_id: text(&q ...

How can we efficiently load paginated data from a database while still implementing pagination using Angular Material?

I have a large table with more than 1000 entries that I want to display using a <mat-table></mat-table>. Since loading all the entries at once would be too much, I am looking to implement pagination and load only 20 entries per page. The chal ...

Get the download URL from Firebase Storage and save it into an array within Firestore

I am currently working on a project to upload multiple image files to Firebase Storage and then store their download URLs in a single array within Firestore. uploadImages(name, images) { for (let i = 0; i < images.length; i++) { const file = ...

Encountering issues with Proxy functionality in the latest versions of Angular 13 and Spring Boot

I've encountered an issue with the proxy configuration in Angular. I'm unsure if it's a problem within my Angular settings or if there's a configuration issue in Spring. For testing purposes, I have a backend built in springboot to han ...

Incorporating Google Pay functionality within Angular applications

I have been attempting to incorporate Google Pay into my Angular project, but I am struggling to find reliable resources. My main issue revolves around the following code... <script async src="https://pay.google.com/gp/p/js/pay.js" onloa ...

TypeScript interface with an optional parameter that is treated as a required parameter

Within my interface, I have a property that can be optional. In the constructor, I set default values for this property, which are then overridden by values passed in as the first parameter. If no properties are set, the defaults are used. I am looking fo ...

Exploring the functionality of Material components within a nested child component

I am facing an issue with my TestComponent, which uses a <mat-stepper> in its template. Due to the specific context of the stepper, I have to programmatically move to the next step instead of using the matStepperNext directive on a button. Here is a ...

ESLint and Prettier are butting heads when trying to run their commands consecutively

My package.json file includes two commands: "format": "prettier --write \"{src,{tests,mocks}}/**/*.{js,ts,vue}\"", "lint": "eslint . -c .eslintrc.js --rulesdir eslint-internal-rules/ --ext .ts,.js,.vue ...

Using Node.js and Typescript to implement a chain of logical AND operations with an array of any length

Setting: I am developing a versatile function that determines a boolean outcome based on logical AND operations. However, the function is designed to handle various types of objects and arrays, each requiring different conditions. Currently, my code look ...

Encountering a 404 error when importing http/server in deno

The file named index.ts is located below import { serve } from "https://deno.land/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b0c3c4d4f0809e8186869e80">[email protected]</a>/http/server.ts"; function ...

What improvements can I implement in this React Component to enhance its efficiency?

Seeking advice on improving the efficiency of this React Component. I suspect there is code repetition in the onIncrement function that could be refactored for better optimization. Note that the maxValue prop is optional. ButtonStepper.tsx: // Definition ...

There is a delay in updating ng-if/ng-hide in real time on the HTML page

Assistance needed for implementing a slight adjustment in AngularJS with TypeScript. The requirement is to change the text of a button for 3 seconds upon clicking, then revert back to its original text. Two HTML elements are created for this purpose, each ...

Can a single data type be utilized in a function that has multiple parameters?

Suppose I have the following functions: add(x : number, y : number) subtract(x : number, y : number) Is there a way to simplify it like this? type common = x : number, y : number add<common>() This would prevent me from having to repeatedly define ...

Enable automatic suggestion in Monaco Editor by utilizing .d.ts files created from jsdoc

I am in the process of creating a website that allows users to write JavaScript code using the Monaco editor. I have developed custom JavaScript libraries for them and want to enable auto-completion for these libraries. The custom libraries are written in ...

What method can be used to specify a function of any signature that returns a particular type in programming?

I am looking to define a unique type that must be a function which, when executed, will always produce an object containing the property type: string. The input parameters for this function are of no concern. For instance: foo(1, 'bar'); // res ...

The module 'PublicModule' was declared unexpectedly within the 'AppModule' in the Angular 4 component structure

My goal is to create a simple structure: app --_layout --public-footer ----public-footer.html/ts/css files --public-header ----public-header.html/ts/css files --public-layout ----public-layout.html/ts/css files In public-layout.html, the stru ...