Utilizing TypeScript generics to accurately extract type information from state during reduction

In the context of a state reducer presented as follows:

const anObject = {
  fruit: 'Apple',
  today: new Date(),
}

function reducer(state, stateReducer) {
  return stateReducer(state);
}

const fruit = reducer(anObject, state => state.fruit);
// It is expected that fruit will be of type string.

const now = reducer(anObject, state => state.now);
// It is expected that now will be of type Date.

I am interested in using Typescript generics to ensure that the output state from

reducer(anObject, state => state.someState)
matches the correct type depending on the data it returns. How can this goal be accomplished? Thank you for your assistance.

An interactive demonstration of the code above can be accessed via this link: https://codesandbox.io/s/adoring-booth-jlnhn

Answer №1

It appears that the return type of the reducer function should exactly match the return type of the provided stateGetter function. Moreover, the stateGetter should receive the same type as its argument as what is passed as the first argument to the reducer.

For example, if S represents the state type and R denotes the return type of stateGetter, you can define the function like this:

function reducer<S, R>(state: S, stateGetter: (state: S) => R): R { /* ... */ }

With this setup, you can achieve the desired inferences:

const fruit = reducer(anObject, state => state.fruit); // Type is: string
const today = reducer(anObject, state => state.today); // Type is: Date

Check out the modified codesandbox with these adjustments.

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

Exploring NodeJS Express Routing Across Various URIs/URLs

In my application, there is a public folder that contains HTML/CSS3/JS code. This folder has two main parts: one with the public facing index.html inside public/web and another with an admin view exclusively for admins. Below is the basic layout: public ...

Issue: unable to establish a connection to 127.0.0.1:465 to send an email

When attempting to send smtp alert messages from my site's email account <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="55363a3b2134362115383a3b263c21307b363">[email protected]</a> to the email addresses of m ...

Communication between Laravel and controller using AJAX for exchanging information

I have a specific AJAX function being called from a view: function gatherProductData() { var productIds = []; $('#compare-widget tbody tr').each(function(i, ele) { productIds[i] = $(ele).data('product-id'); }); ...

How can I make the footer on my webpage have a white background?

My goal is to create a white div that spans from point (A) to point (B) on the page, just like in the image. I aim for it to stretch all the way down to cover the entire browser without showing any gray background underneath, even when the page is scrolled ...

What's the best way to keep track of the number of objects I've created

Using this HTML code, I can create member objects. However, I also need to determine the count of these member objects for certain calculations. Additionally, when a member object is deleted, the count of member objects should be reduced accordingly. The ...

"Encountered an issue with ng-annotate during processing

I'm attempting to utilize ng-annotate on my Angular application, but it seems to be not working at all. Here is the configuration part: (function () { 'use strict'; angular.module('app') .config(/*@ngInject*/ ro ...

Why won't both routes for Sequelize model querying work simultaneously?

Currently, I am experimenting with different routes in Express while utilizing Sequelize to create my models. I have established two models that function independently of one another. However, I am aiming to have them both operational simultaneously. A sea ...

Finding the Number of Days Between Two Dates in AngularJS Using JavaScript

When I receive two dates from a web service in the format below: var dateone = "2016-08-21T07:00:00.000Z"; var datetwo = "2016-08-28T07:00:00.000Z"; var datediff = datetwo - dateone; var numdays = Math.round(datediff); console.log("Number of Days is " + n ...

Exploring the World of Browserify Submodules

/xyz /abc.js /abcdef.js /index.js When working with node.js, if you use the require statement for a directory (require('xyz')), it will automatically search for an index.js file within that directory and return the exports defined in that ...

ReadOnly types in Inheritance

Currently, I am working on creating an unchangeable, nested data structure that also incorporates inheritance. To achieve this, I am using the Readonly generic type. In order to create different types within this structure, one of these Readonly types need ...

Sharing information between controllers while being initiated using $rootScope.$emit

I've created a common module that includes a controller, component, and template to initialize the app and set up the base layout. Within this module, there is also a stateful component that makes an HTTP GET request during initialization to fetch a b ...

How can TypeORM be used to query a ManyToMany relationship with a string array input in order to locate entities in which all specified strings must be present in the related entity's column?

In my application, I have a User entity that is related to a Profile entity in a OneToOne relationship, and the Profile entity has a ManyToMany relationship with a Category entity. // user.entity.ts @Entity() export class User { @PrimaryGeneratedColumn( ...

When using <body onload=foo()>, the function foo will not be executed

Having trouble with this code - it seems like initialize() is not being called. Check out the code here Any insight into why this might be happening? ...

Deleting a property once the page has finished loading

My issue is a bit tricky to describe, but essentially I have noticed a CSS attribute being added to my div tag that seems to come from a node module. The problem is, I can't seem to find where this attribute is coming from in my files. This attribute ...

Showing the initials of a user at the top of an SVG using ReactJS

https://i.sstatic.net/oJgXs.png I require the user's initials to be displayed on the avatars as a grey circle with those initials. I have the function ready, but I am unsure of how to implement it in the JSX code for the Dropdown menu (using Semantic ...

Difficulty loading AJAX with autocomplete feature. Any suggestions?

I have created a jQuery autocomplete feature that works correctly, but when the value is removed using the Backspace key, the 'LOADING...' message remains visible instead of hiding. How can I make it so that after removing the value with the Back ...

Utilize Angular to simultaneously filter search results by URL and make selections in a dropdown menu

As a newcomer to the Angular JS framework, I have successfully created a client-company table where clients can be filtered by company name using a drop-down menu. However, I am now looking to implement a filtering mechanism based on the URL structure su ...

Obtaining a substantial pdf file using html2pdf

While using html2pdf to generate a PDF of my website, I noticed that the downloaded PDF ends up being 14 pages long. However, after approximately 12 pages, all the colored elements seem to disappear. On mobile screens, this issue occurs even sooner, around ...

The presence of ng-show dynamically adjusts the minimum height of a div element

I am encountering an issue with a div that has the class of wrapper. Inside this div, there is a parent div with the class of content-wrapper. The wrapper div includes a conditional directive ng-show which toggles between displaying or hiding its content. ...

Axios mandating the use of the "any" type for response type requirements

Currently, I am facing an issue while trying to retrieve data using Axios in my TypeScript React project. I have set the response type in axios to match CartItemType, however, Axios is enforcing the response type to be of CartItemType and any, which is cau ...