Deduce the generic types of conditional return based on object property

My goal is to determine the generic type of Model for each property. Currently, everything is displaying as unknown[] instead of the desired types outlined in the comments below.

playground

class Model<T> { x?: T }

type ArgumentType<T> = T extends Model<infer TInner> ? Model<TInner> : (
        T extends Model<infer TInner>[] ? Model<TInner>[] : never
    );

type ReturnType<T> = T extends Model<infer TInner> ? TInner[] : (
        T extends Model<infer TInner>[] ? TInner[][] : never
    );

const test = <TInner, TValue extends ArgumentType<TInner>, T extends Record<string, TValue>>(models: T): Record<keyof T, ReturnType<TValue>> => {

        return;
    }

const numberModel = new Model<number>();
const stringModel = new Model<string>();
const bigintModel = new Model<bigint>();

const result = test({
    prop1: [numberModel, numberModel, numberModel],
    prop2: [stringModel],
    prop3: stringModel,
    prop4: [numberModel, numberModel, numberModel, bigintModel],
    prop5: stringModel
});

//expected types
result.prop1 // number[][]
result.prop2 // string[][]
result.prop3 // string[]
result.prop4 // (number | bigint)[][]
result.prop5 // string[]

//actual types
result.prop1 // unknown[]
result.prop2 // unknown[]
result.prop3 // unknown[]
result.prop4 // unknown[]
result.prop5 // unknown[]

Answer №1

Here is a suggestion for your test() function with a revised call signature:

declare const test: <T extends Record<keyof T, Model<any> | Model<any>[]>>(
  models: T
) => { [K in keyof T]:
    T[K] extends Model<infer U> ? U[] :
    T[K] extends Model<infer U>[] ? U[][] :
    never
}

In this updated version, we utilize a single generic type parameter T constrained to

Record<keyof T, Model<any> | Model<any>[]>
, which simplifies the inference process for TypeScript's compiler.

The output type definition is based on the properties of T, similar to the ReturnType<> alias but mapped over each property key K corresponding to models.


For testing purposes, consider the following example:

const numberModel = new Model<number>();
const stringModel = new Model<string>();
const bigintModel = new Model<bigint>();

const result = test({
  prop1: [numberModel, numberModel, numberModel],
  prop2: [stringModel],
  prop3: stringModel,
  prop4: [numberModel, numberModel, numberModel, bigintModel],
  prop5: stringModel
});

/* Result:
    prop1: number[][];
    prop2: string[][];
    prop3: string[];
    prop4: (number | bigint)[][];
    prop5: string[];
*/

Test successful!

Link to playground with code

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

Express fails to pass password validation

I encountered an issue with a ValidationError stating that the Path password is required while attempting to register a new User. My experience in Node, programming, and authentication is limited. Below is the code for the User model and schema where I ma ...

Having trouble with JQuery's append method on the <head> tag?

I am having an issue with this particular code block. It seems to be unable to insert the meta tag into the head section. Any suggestions on how to resolve this problem? <html> <head> <title>hello world</title> </head> < ...

Displaying dynamic key-value pairs in each row of an Angular mat-table

I need help displaying a key-value pair data in JSON format dynamically within a table using Angular mat-table. The keys will vary, so there is no set list of keys that will be included in the JSON. This is an example of the data: var data = { "cars" : 2 ...

Finding a workaround for the absence of a leftToggle feature in ListItem component of Material-UI

Is there a way to move the toggle element to the other side in Material-UI's listItem without using the leftToggle option? The documentation does not specify a leftToggle attribute, so I am looking for alternative solutions. I would like to align the ...

The functionality of the Bootstrap carousel may be compromised when initialized through JavaScript

Why isn't the Bootstrap carousel working in the example below? It starts working when I paste it into .content <head> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> <script sr ...

I am experiencing issues with the customsort function when trying to sort a column of

Seeking assistance with customizing the sorting function for a Date column in a primeng table. Currently, the column is displaying data formatted as 'hh:mm a' and not sorting correctly (e.g. sorting as 1am, 1pm, 10am, 10pm instead of in chronolog ...

Troubleshooting Bootstrap 3.0: Issues with nav-tabs not toggling

I have set up my navigation tabs using Bootstrap 3 in the following way: <ul class="nav nav-tabs pull-right projects" role="tablist" style="margin-top:20px;"> <li class="active"><a role="tab" data-toggle="tab" href="#progress">In Pr ...

Extracting data from a JSON object using Angular

Recently, I've been delving into the world of AngularJS and encountered a hurdle with LocalStorage. After spending numerous hours trying to figure out how to save data locally, I believe I have finally got it working as intended. Now, my next challeng ...

Incomplete JSON response being received

We set up an express server to call an API and successfully requested the JSON object in our server. However, we are facing an issue where the JSON data is getting cut off when being displayed as a complete object on the client side. We tried using parse i ...

Is your Firebase .push() function encountering errors when trying to update the database?

I am facing an issue with a component that checks if a user has already upvoted a post. The logic is such that if the user has upvoted a post before, they cannot upvote it again. However, if they haven't upvoted it yet, they should be able to do so. ...

Tips for implementing collapsible functionality that activates only when a specific row is clicked

I need to update the functionality so that when I click on a row icon, only that specific row collapses and displays its data. Currently, when I click on any row in the table, it expands all rows to display their content. {data.map((dataRow ...

What is the proper way to update data in reactjs?

I previously had code that successfully updated interval data in the browser and locale without any issues. class Main extends Component { constructor(props) { super(props); this.state = {data: []} } componentWillMount() { fetch('fi ...

Custom cellRenderer prevents Ag Grid's autoHeight and wrapText features from functioning properly

I've been attempting to adjust the formatting of a long cell value by wrapping the text. According to the documentation, setting autoHeight=true and wrapText=true works fine without any cellRenderer components. However, when using a cellRendererFramew ...

Instantly magnifying on the initial point regardless of the zoom type chosen is a feature of Chart.js zoom

Despite adding zoom functionality to my line chart, I am facing an issue where it automatically zooms in to the first point and does not allow me to zoom back out, except for using the reset zoom function. The zoom out function is also not working properly ...

jQuery divs seem to "gaze up" towards the mouse pointer

I am attempting to recreate a fascinating effect using jQuery - where "cards" move in response to the mouse cursor as if they are looking up at it. I have come across a script that almost achieves what I need, but I require the ability to control the mov ...

Implementing key strokes in an HTML input field within a geckoWebBrowser

I am currently using the "geckoWebBrowser1" component to navigate to a URL that displays a login textbox with the ID: login-email Although I have successfully inserted "[email protected]" into the aforementioned textbox, it is essential to simulate k ...

How do I show a variable within my react-native render function?

I attempted to showcase information fetched by a function in my React Native rendering application. Even though I successfully retrieved the data, I am encountering issues when trying to display it on the app. This is the snippet of my code: import Reac ...

How to retrieve the clicked value using jQuery within a jinja2 loop

I'm currently working on an app that utilizes a Flask backend and Jinja2 templating. Within the HTML, I have a loop set up to organize data into batches, creating three columns on the web page: {% for batch in df.iterrows() | batch(3) %} <d ...

Mapping the preselected values of multiple input fields into an array in Angular 6: A step-by-step guide

When submitting a form with input fields, I need to capture the selected values into an array format like {"userid":1,"newstatus":[1],"mygroup":[1,2,3]}. I attempted using ngmodel but encountered issues. Below is the code snippet: home.component.html & ...

Unable to determine why node.js express path is not working

const express = require("express"); const app = express(); app.use(express.static("public")); var dirname = __dirname; app.get("/:lang/:app",function(req,res){ console.log(req.params.lang + " " + req.params.app); ...