Monitor a universal function category

Trying to implement a TypeScript function that takes a single-argument function and returns a modified version of it with the argument wrapped in an object. However, struggling to keep track of the original function's generics:

    // ts v4.5.5

    type FnType<Arg, Ret> = (arg: Arg) => Ret
    
    type Wrapped<VFn extends FnType<any, any>> = (wrap: {
      _: VFn extends FnType<infer A, any> ? A : never
    }) => VFn extends FnType<any, infer B> ? B : never
    
    // Created a function that takes a `FnT extends FnType` and produces Wrapped<FnT>
    type Wrapper = <FnT extends FnType<any, any>>(v: FnT) => Wrapped<FnT>
    declare const wrapper: Wrapper
    
    // The resulting `wrapped` function loses track of generic type T
    const wrapped1 = wrapper(<T>(t: T) => ({ t })) // const wrapped1: Wrapped<(<T>(t: T) => { t: T; })>
    const ret1 = wrapped1({ _: { a: 1 } }) // const ret1: { t: unknown; }
    
    
    type MyFnType = <T>(t: T) => { t: T }
    const myFnType:MyFnType = <T>(t: T) => ({ t })
    
    // Even explicitly defining and passing FnType as generic and argument !
    
    const wrapped2 = wrapper<MyFnType>(<T>(t: T) => ({ t })) // const wrapped2: Wrapped<MyFnType>
    const ret2 = wrapped2({ _: { a: 1 } }) // const ret2: { t: unknown; }
    
    const wrapped3 = wrapper<MyFnType>(myFnType) // const wrapped3: Wrapped<MyFnType>
    const ret3 = wrapped2({ _: { a: 1 } }) // const ret3: { t: unknown; }

Check code on TS sandbox

Answer №1

When utilizing a conditional type to extract parameters and return types in TypeScript, generics are not preserved through functions.

To maintain generics, you can use the args and return type as type parameters when defining the function:

type Wrapper = <A, R>(v: (a: A) => R) => (a: { _: A }) => R
declare const wrapper: Wrapper


const wrapped1 = wrapper(<T>(t: T) => ({ t }))
const ret1 = wrapped1({ _: { a: 1 } }) // const ret1: { t: { a: number }; }

Visit Playground Link for more details

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

Encountered difficulty locating the module path 'stream/promises'

When importing the following in a typescript nodejs app import { pipeline } from "stream/promises"; Visual Studio Code (vscode) / eslint is showing an error message Unable to resolve path to module 'stream/promises' This issue appeare ...

Creating an array of strings using data from a separate array of objects in JavaScript/TypeScript

I want to generate a new array of strings based on an existing array of objects, with each object belonging to the Employee class and having a firstName field: assignees: Array<Employee>; options: string[]; I attempted to achieve this using the fol ...

Error encountered while transforming object due to index type mismatch

I am attempting to change the values of an object, which consist of arrays with numbers as keys, to their respective array lengths. However, I received a type error that says 'Element implicity has any type because a string element cannot be used to ...

Managing clicks outside of the render function

I'm brand new to using React and I'm currently exploring how to properly manage an event handler outside of the Return() function within a component. If there's a more efficient or conventional way to do this, I'm definitely open to sug ...

Exploring the new possibilities of Angular 5: Enhanced REST API service with paginated data and object mapping capabilities

After implementing pagination in my REST API backend, I now need to update my Angular services to accommodate the changes. Instead of simply returning an array of objects, the API will now return JSON responses structured like this: { "count": 0, ...

ESLint is reporting an error of "Module path resolution failed" in a project that includes shared modules

Encountering ESLint errors when importing modules from a shared project is causing some frustration. The issue arises with every import from the shared/ project, presenting the common ESLint import error: Unable to resolve path to module 'shared/hook ...

To collapse a div in an HTML Angular environment, the button must be clicked twice

A series of divs in my code are currently grouped together with expand and collapse functionality. It works well, except for the fact that I have to click a button twice in order to open another div. Initially, the first click only collapses the first div. ...

Configuring ordered imports in TSLint

Need help with configuring my TSLint rule ordered-imports. I want the import order to be like this: // React import React from 'react'; import { View } from 'react-native'; // Libs import * as _ from 'lodash'; import * as mo ...

Trouble setting custom attribute tags in Ionic 4

Trying to apply custom attributes within a ngFor loop is proving challenging for me. <ng-container *ngFor="let a of this.current_items?.areas; let i = index"> ... I've made several attempts: <div class="productBatchArea" custom-data=&apo ...

The Karma ng test fails to display any build errors on the console

I've encountered a frustrating issue while working with Karma and Jasmine for testing in my Angular 7 project. The problem arises when there are errors present in the .spec.ts or .ts files, as running ng test does not display these errors in the conso ...

Transferring data between unrelated components

I am facing an issue where I am unable to pass a value from the Tabs component to the Task component. To address this, I have created a separate data service. The value in the Tabs component is obtained as a parameter from another component. However, when ...

Encountered an issue during the transition from Angular 7 to Angular 9

After following the advice in the second response of this discussion, I successfully upgraded to Angular 9. However, I am now encountering an issue in the browser console when running my project. Package.json "dependencies": { "@angular-devkit/build- ...

What is the proper way to create an array of dynamically nested objects in TypeScript?

Consider the structure of an array : [ branch_a: { holidays: [] }, branch_b: { holidays: [] }, ] In this structure, branch_a, branch_b, and ... represent dynamic keys. How can this be properly declared in typescript? Here is an attempt: ty ...

JavaScript: specify parameters for function inputs

I'm curious about optimizing Javascript/Typescript functions arguments for clean code. To demonstrate, let's consider a basic example. Imagine I have a React component with a view property as props: <Grid view="Horizontal" /> ty ...

Angular's array filter functionality allows you to narrow down an

I am working with an Array and aiming to filter it based on multiple criteria: primasSalud = [ { nombre: 'one', internacional: true, nacional: false, nacionalSinReembolso: false, nacionalClinicasAcotadas: false ...

Handling Errors in Angular 4

If a client sends a POST request with a LicenseNumber that already exists in the database (and must be unique), the server will respond as follows: {"errorCode":"Validation Error", "errorMessage":"Invalid inputs.", ...

Guide on packaging an Angular 2 Typescript application with Gulp and SystemJS

In my Angular 2 project, I am using Typescript with SystemJS for module loading and Gulp as a task runner. Currently, the project is running on Angular RC2 but the same issue persists with RC1. I followed the steps provided in brando's answer here. U ...

Angular - optional parameter in route using ngRouter

I have a question regarding using Angular (4) with the @angular/router. I want to be able to include optional parameters in a path style, but am facing some challenges. Currently, my code looks like this: { path: 'cars', component: CarComponent ...

calculate the difference between two dates and then add this difference to a new date

Utilizing TypeScript for date calculations. Example: Initial Date 1: "10/06/2021 10:10:05" Initial Date 2: "08/06/2021 11:10:05" Calculate the difference between the two dates, including date/month/year/hour/min/sec/milliseconds. Ensure compatibility wi ...

Unlinked Typescript blob file name

Is there a way to set the file name for a blob in typescript? I have found a solution for IE, but it seems impossible for Chrome. I need something similar to this solution, but in typescript. downloadFile(data: any) { var blob = new Blob([data], {type ...