Determine the type of the final function within a variable number of nested closures

Imagine you have a function like this:

const f = a => b => ... x => { return somevalue }

Is there a way to determine the type of just the final function

typeof x => { return somevalue }
even if we don't know how many closures come before it?

One idea is to create a type that uses recursion and conditional type checking to navigate through the closures until reaching the end. However, it's unclear if TypeScript supports recursive types for solving this specific issue.

Answer №1

Recursive conditional types are set to debut in TypeScript 4.1. In the meantime, you can access this feature by using typescript@next. Once available, you'll be able to define something like:

type LastFunc<T extends (...args: any) => any> =
    T extends (...args: any) => infer R ? 
    R extends (...args: any) => any ? LastFunc<R> : T : never;

You can apply it to your function f as follows:

declare const somevalue: SomeValue;
const f = (a: any) => (b: any) => (c: any) => (d: any) => (x: any) => { return somevalue }
type LastFuncF = LastFunc<typeof f>; // type LastFuncF = (x: any) => SomeValue

Playground link to code


In the interim, there are two ways to achieve similar results. The first is a workaround that may not be officially supported but gets the job done:

type LastFunc<T extends (...args: any) => any> =
    T extends (...args: any) => infer R ? {
        0: LastFunc<Extract<R, (...args: any) => any>>, 1: T
    }[R extends (...args: any) => any ? 0 : 1] : never

The second method involves manually unrolling the loop to a fixed depth which can be tedious and repetitive:

type LastFunc<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LF0<R> : T : never;
// Additional LFX definitions...

Playground link to code


If I were in your shoes, I'd recommend waiting for TypeScript 4.1's release. Best of luck with your coding endeavors!

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

Variability in Focus Behavior while Opening a URL in a New Tab with window.open()

Here is a code snippet I have been using to open a URL in a new tab: window.open(urlToOpen, '_blank', 'noopener noreferrer'); The issue I am experiencing is that when this code is executed for the first time, it opens the URL in a new ...

Having trouble implementing the ternary operator (?) in TypeScript within a Next.js project

Trying to implement a ternary operator condition within my onClick event in a Next.js application. However, encountering an error indicating that the condition is not returning any value. Seeking assistance with resolving this issue... https://i.stack.img ...

Use bracket notation to verify if a property is undefined

Having some difficulty determining if the property value of an object is undefined when accessed dynamically with bracket notation. Here's a snippet of my code: function toBritishDate(date: Date | string): string { console.log(date) return &qu ...

Importing libraries in TypeScript and JavaScript are not done in the same manner

As I create my own library, I aim for it to be compatible with both javascript and typescript. tsconfig.json { "compilerOptions": { "target": "es2017", "module": "commonjs", &qu ...

Do [(ngModel)] bindings strictly adhere to being strings?

Imagine a scenario where you have a radiobutton HTML element within an angular application, <div class="radio"> <label> <input type="radio" name="approvedeny" value="true" [(ngModel)]=_approvedOrDenied> Approve < ...

Error encountered during unit testing: The function _reactRouterDom.useHistory.mockReturnValue is not a valid function

I'm having trouble writing unit tests for a React component implemented in TypeScript. I encountered an error when trying to mock some hook functions. Here is my current unit test implementation: import React from 'react'; import { useHisto ...

How can the panel within an accordion be enlarged or minimized?

Currently, I am implementing an accordion feature with the option to expand or collapse all panels using two buttons. My goal is to allow users to manage each panel within the accordion individually. However, I have encountered an issue that needs attenti ...

Utilizing the Pub/Sub architecture to integrate the kafka-node library within Node Js

Utilizing the kafka-node module in my NodeJs Microservise project, I am aiming to implement a Pub/Sub (publisher and subscriber) design pattern within the Functional programming paradigm. producer.js const client = new kafka.KafkaClient({ kafkaHost: ...

Discovering the ReturnType in Typescript when applied to functions within functions

Exploring the use of ReturnType to create a type based on return types of object's functions. Take a look at this example object: const sampleObject = { firstFunction: (): number => 1, secondFunction: (): string => 'a', }; The e ...

An issue has occurred: The function _co.deleteConsulta is not recognized as a valid function

While following a tutorial on creating a CRUD application using Firestore, I encountered an issue when trying to delete data from Firestore. Every time I attempt to delete a user from my Firestore database, I receive an error stating that ._co.deleteConsul ...

What is the equivalent of a "Class" in Typescript for defining an "Interface"?

I am interested in passing "Interfaces" to a function. Not just a specific interface, but any interfaces. As explained here, for Class, I can handle it as a type. export type ClassType<T> = { new(...args: any[]): T }; function doSomethingWithAnyCla ...

The error message "Type 'IPromise<{}>' is not compatible with type 'IPromise<TemplatesPagingModel>' in typescript version 2.8.0" is displayed

Currently, I am working on an AngularJS framework (version 1.5.8) with the latest TypeScript files (version 2.8.0). However, after updating to the most recent TypeScript version, the code below is not compiling. Implementation of Angular interface: inter ...

What is the best way to evaluate typing into an input field?

My objective is to test the 'typing' functionality in an input element. The aim is to insert a value into the input element, verify that its binding successfully captures the value, and observe the entered value within the input element. Below i ...

Setting limits to disable or remove specific times from the time picker input box in Angular

I'm having trouble with a time input box. <input type="time" min="09:00" max="18:00" \> Even though I have set the min and max attributes to values of 09:00 and 18:00 respectively, it doesn't seem to be working properly. I want to ...

Oops! There seems to be an issue with locating a differ that supports the object '[object Object]' of type 'object', like an Array

I'm currently encountering an error that reads: (ERROR Error: NG02200: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables, such as Arrays. Did you mean to use the key ...

Ways to generate an Angular 7 component

Seeking guidance on creating an angular 7 component. I have forked a jsFiddle at this link: https://jsfiddle.net/gauravshrestha/fdxsywLv/. The chart in the fiddle allows data points to be dragged up and down. My goal is to convert this into a component whe ...

Discover the subsite inventory of a SharePoint site using TypeScript

Is there a way to gather all sub-sites from my SharePoint site and organize them into a list? I initially thought of using this.context.pageContext, but could not locate it. Please excuse my seemingly simple question, as I am still learning TypeScript. ...

Error: The Turborepo package restricts the use of import statements outside of modules

I created a typescript "test" package in turborepo, which imports and exports typescript functions. Due to being in turborepo, it gets copied to node_modules/test. When attempting to run import {func} from "test", an error is thrown: SyntaxError: Cannot ...

Execute an Asynchronous Operation in NgRx After Triggering an Action

Please note that this is a question seeking clarification Instructions Needed I am currently working on dispatching an action to NgRx in order to add a task to a list of tasks. Additionally, I need to perform a put request to an API to save the changes ma ...

leveraging third party plugins to implement callbacks in TypeScript

When working with ajax calls in typical javascript, I have been using a specific pattern: myFunction() { var self = this; $.ajax({ // other options like url and stuff success: function () { self.someParsingFunction } } } In addition t ...