Using the `infer` keyword to deduce a type parameter in a generic function

When working with TypeScript, it is possible for a generic function to be automatically generated if one of the parameters is a type parameter from another generic function. This can happen without explicitly defining it as a generic.

export function fn<P, R>(cb: (param: P) => R) {
  // No explicit generic definition
  return (param: P, extra?: unknown) => {
    console.log(extra)
    return cb(param)
  }
}

// `f` is inferred as generic -- const f: <S>(param: S, extra?: unknown) => S
const f = fn(<S>(str: S) => str)
const returned = f("value") // typeof returned is `"value"`

However, there seems to be an issue when trying to achieve this using ordinary types and the infer keyword.

export type Fn<T extends (param: never) => unknown> = T extends (
  param: infer P
) => infer R
  ? (param: P) => R
  : never

// type F = `(param: unknown) => unknown` instead of `<V>(v: V) => V`
type F = Fn<<V>(v: V) => V>

Are there any solutions or details that I might have overlooked?

In continuation with the discussion on the fn method, it was observed that TypeScript does not infer a generic anymore if the function is overloaded, which may be a problem in specific scenarios.

export function fn<P, R>(cb: { (): ""; (param: P): R }) {
  // No explicit generic definition
  return (param: P, extra?: unknown) => {
    console.log(extra)
    return cb(param)
  }
}

// typeof f is not generic if function is overloaded
// const f: (param: { value: unknown; }, extra?: unknown) => unknown
const f = fn({} as unknown as { (): ""; <S>(str: S): S })
const returned = f({ value: "value" as const }) // typeof returned is `unknown`

Is there a solution available to resolve this issue?

Answer №1

To improve your type, consider making the following adjustments:

export type NewFn<X> = X extends <Y>(
  input: Y
) => Y
  ? <Y>(input: Y) => Y
  : never;

type G = NewFn<<Z>(z: Z) => Z>; 

By implementing these changes, G will have the correct type inference.

const result1: G = <A, >(value: A) => value;

const output1 = result1('value') // the type of output1 will be 'value'
const output2 = result1({ val: 2 }) // the type will be { val: number }

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

The IDE is showing an error, but Jest is able to run it flawlessly

I recently created a Jest unit test for a TypeScript function called checkEmail, which internally uses showAlert. The showAlert function in the utils.ts file looks like this: export const showAlert = (message: string) => { toast(message); }; In my ...

Troubleshoot: Angular 12 HTTP request not passing correct parameters

When working with my service.ts file, I encountered an issue while calling a method that triggers an http request to the specified API endpoint: users/1111/state/2222 The numbers 1111 and 2222 represent the userId and stateId respectively. This is the sni ...

Injecting class names into styled components while typing

Can someone assist me in correcting my code? I am trying to add class names to styled components using a custom function. Here is what I have: type IntrinsicElementsKeys = keyof { div: any, a: any } /* could be keyof JSX.IntrinsicElements */ export funct ...

TS4060: The export function's return type refers to a private name 'class' which is being used

I'm facing an issue here. Typescript keeps throwing this error: TS4060: Return type of exported function has or is using private name 'class' Student test.ts export default function EXPORTMODULE(GreetingText:string) { class Stud ...

Updating the property value of an element in Angular 9

I'm facing an issue where I can't change the attribute value of an element successfully. Is there a best practice in Angular that can help solve this problem? <div name="hai" (click)=test($event) #ckechName> In the TypeScript ...

Locating a class variable using a string chosen from a DropDown menu

In my Tv class, I have several string variables. One requirement is for the user to select an option from a DropDown list and input a value. This entered value should then be stored in the Tv class under a variable with a similar name to the selected optio ...

"Exploring the power of Knex in combination with Typescript and Electron. However, encountering node_module errors

I currently have a functioning Electron application that utilizes Typescript. The main.ts file is specifically for the main process. import { app, BrowserWindow } from 'electron'; import * as path from 'path'; import * as url from &apos ...

The Angular 2 application is experiencing issues with displaying the Bootstrap 4.3 Modal

I am new to Angular so please forgive me if this question sounds silly. I am trying to implement a modal in my app and I followed an example from Bootstrap's documentation. However, the modal doesn't seem to work in my app. Everything else has be ...

Angular 4 Web Application with Node-Red for Sending HTTP GET Requests

I am creating a unique service that utilizes Node-red to send emails only when a GET request is made to 127.0.0.1:1880/hello (node-red port), and an Angular 4 web app (127.0.0.1:3000) for client access. Upon accessing the /hello page from a browser, I rec ...

Is there a way to customize the look of the time selected in the <input matInput type="time" step="1" /> time picker?

Currently, I am utilizing the following code as a time picker in my Angular 9 application. My goal is to modify the selected time's color to a bright blue shade. How can I accomplish this task? <input matInput type="time" step="1&quo ...

MongoDB NextJS connection issue "tried to retrieve a connection from a closed connection pool"

I am attempting to establish a connection to my MongoDB database in order to retrieve some information. When setting up the connection without fetching any data, everything works fine. However, when trying to fetch data, the console throws this error: at ...

Is there a way to access every item that includes a particular attribute and attribute term within the woocommerce-rest-api?

Struggling to retrieve products that have the "x-attribute" and "x-attribute-term" using Node.js with the WooCommerce REST API library from here. I've explored solutions on stackoverflow and other sites but none seem to work. Atte ...

Creating an array from a numerical value in Angular Controls

In my application, I need to create an array starting from 1 up to a specified number, which in this case is 6, using JavaScript/TypeScript. Here is my attempted code: this.builder.group({ 'staff': this.builder.group({ staf ...

Conceal Server Side Components from Client Side Components in Next JS

I am currently facing a dilemma with Next.js. My goal is to toggle the visibility of a server-side component (show/hide) from my client-side component, but I cannot directly integrate server-side code into the client component as per the restrictions. At t ...

Including a Javascript library (jsencrypt) in an Angular 2 application

I have gone through countless tutorials on this particular issue, but unfortunately, I have not yet found a solution. Let me provide some context first. I am working on an Angular 2 application and I need to incorporate this JS library for encryption: http ...

Guide to mocking the 'git-simple' branchLocal function using jest.mock

Utilizing the simple-git package, I have implemented the following function: import simpleGit from 'simple-git'; /** * The function returns the ticket Id if present in the branch name * @returns ticket Id */ export const getTicketIdFromBranch ...

Passing extra arguments to a callback function in Typescript

I'm trying to pass a parameter to a callback function. Below is the snippet of my function: let func = function(el, index){ if(el.id === myId) return index; } arr = [obj1, obj2, obj4, ...]; arr.filter(func); Is there a way to suc ...

Is it recommended to utilize `await` when invoking an `async` function within another `async` function?

In my code, there is an async function that calls another async function: const func1 = async () => {...} const func2 = async () => {func1()} I am curious whether it is necessary or redundant to use await when calling func1() inside func2 ? const f ...

Mastering the Implementation of APP_INITIALIZER in Angular

I have an Angular 5.2.0 application and I wanted to implement the use of APP_INITIALIZER to load configuration data before the app starts. Below is a snippet from my app.module: providers: [ ConfigurationService, { provide: APP_INITIALIZER ...

Angular 2 is having trouble with object dot notation in Typescript and is expecting a semicolon

Hello, I am currently transitioning a project from Angular 1 to TypeScript and Angular 2. One issue I'm facing is getting some property definitions into the Angular 2 component. Below are the property definitions causing trouble: import { Component ...