Why does TypeScript require a generic type parameter when arguments have already been provided?

When I attempted to use the argument p to infer type P, TypeScript still prompted me to provide type P. Why is that?

const numberStringConverter = <T extends string | number,P extends {x: any}>(p: P): T => {
  if(typeof p.x === 'string'){
    return Number(p.x) as T
  }
  if(typeof p.x === 'number'){
    return String(p.x) as T
  }
  return p.x as T;
}
const ret = numberStringConverter<string>({x:1}) // Expected 2 type arguments, but got 1.

I encountered a similar issue on https://github.com/Microsoft/TypeScript/issues/10571, although I am uncertain about it.

This example is simplified, and there may be alternative ways to approach this problem.

Answer №1

P extends {x: any} in this scenario, you are indicating to accept any extended object of type {x:any}

You should specify One and Two classes for reporting purposes

interface Base {x:any}

interface One extends Base {
  y?:string
}

interface Two extends Base {
  z?:string
}


const numberStringConverter = <T extends string | number,P extends Base >(p: P): T => {
  if(typeof p.x === 'string'){
    return Number(p.x) as T
  }
  if(typeof p.x === 'number'){
    return String(p.x) as T
  }
  return p.x as T;
}


 numberStringConverter<string,One>({x:1});
 numberStringConverter<string,Two>({x:1});

If only one class is accepted, avoid using extends and directly pass the class as a parameter

const numberStringConverter2 = <T extends string | number,>(p: Base): T => {
      if(typeof p.x === 'string'){
        return Number(p.x) as T
      }
      if(typeof p.x === 'number'){
        return String(p.x) as T
      }
      return p.x as T;
    }

You can also utilize it differently. If Generic does not have a specified type, it defaults to any.

    const numberStringConverter = <T extends string | number,P extends {x: any}=any>(p: P): T => {
      if(typeof p.x === 'string'){
        return Number(p.x) as T
      }
      if(typeof p.x === 'number'){
        return String(p.x) as T
      }
      return p.x as T;
    }
    
    
     numberStringConverter<string>({x:1});
     numberStringConverter<string>({x:1});
    
    
    // The issue with this approach is that the ts compiler won't flag an error here 
//and the p.x line in the function will cause an error at runtime
    // has to be identified during runtime
     numberStringConverter<string>(5);

However, I believe this method suits your requirements best.

interface Base { x:any}

const numberStringConverter = <T extends string | number,P extends Base =Base>(p: P): T => {
  if(typeof p.x === 'string'){
    return Number(p.x) as T
  }
  if(typeof p.x === 'number'){
    return String(p.x) as T
  }
  return p.x as T;
}


 numberStringConverter<string>({x:1});
 numberStringConverter<string>({x:1});

 // ts compiler will show error
 numberStringConverter<string>(5);

P extends Base =Base where you define that this type is the default unless a specific generic type is provided.

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 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 ...

Updating an object property within an array in Angular Typescript does not reflect changes in the view

I am currently delving into Typescript and Angular, and I have encountered an issue where my view does not update when I try to modify a value in an array that is assigned to an object I defined. I have a feeling that it might be related to the context b ...

How can I conceal the word "null" within an Angular 2 input field?

Whenever there is a null value in the JSON, it ends up displaying in the input field. How do I go about hiding it so that only the name shows up instead? <div> <input type="hidden" name="roleUserHidden-{{roleIndex}}" #role ...

The Angular NGRX action payload seems to undergo modifications between dispatching and execution

Angular v10, NGRX v10 I am facing a perplexing issue with my Plan object and Task properties using Angular v10 and NGRX v10. Despite making updates to Task properties within my TaskService by deep cloning the Plan object and dispatching an Action to updat ...

Guide on Applying a Dynamic Color in VueJs 3 Composition API/Vuetify Using CSS

Currently, my project utilizes Vue 3 with the composition API and Vuetify for the UI. I am looking to utilize a color that is already defined in a Vuetify theme variable within my CSS, similar to how I have done it previously in JavaScript. Although I at ...

$(...).parentElement is not a function - Troubleshooting a Problem with WebDriver IO and TypeScript

Alright, the objective is simple. I need to ascend from the root to obtain its parent element. Following the webdriver documentation, it should resemble something like this: it('should retrieve the class from the parent element', async () => { ...

Using Angular to create a dynamic form with looping inputs that reactively responds to user

I need to implement reactive form validation for a form that has dynamic inputs created through looping data: This is what my form builder setup would be like : constructor(private formBuilder: FormBuilder) { this.userForm = this.formBuilder.group({ ...

Circular reference in Angular/TypeScript

I encountered a circular dependency issue in my Angular project and tried various solutions, including exporting all dependent classes from a "single file" as suggested here. Unfortunately, this approach did not work for me. I then explored other solutions ...

The subscribe method in Angular TS may be marked as deprecated, but worry not as it is still

I have developed a function that retrieves new data from a service file each time it is called. Here is how the function looks: onCarChange() { this.carService.getCarData(this.selectedCar).subscribe( async (response: CarData) => { if (response?.d ...

"TypeORM's createConnection function on MacOS with PG database returns a Pending status even when using

Running MacOS Catalina version 10.15.4 To replicate the issue, follow these steps using the quick guide: npm install typeorm --save npm install reflect-metadata --save npm install @types/node --save npm install pg --save npm install typeorm -g typeorm in ...

NextJS VSCode Typescript results in breakpoints becoming unbound

I have been following the instructions provided by Next.js from their official documentation on debugging using Visual Studio Code found here: https://nextjs.org/docs/advanced-features/debugging#using-the-debugger-in-visual-studio-code When attempting to ...

`Drizzle ORM and its versatile approach to SELECT statements`

Looking to improve the handling of options in a function that queries a database using Drizzle ORM. Currently, the function accepts options like enabled and limit, with potential for more options in the future. Here's the current implementation: type ...

A special function designed to accept and return a specific type as its parameter and return value

I am attempting to develop a function that encapsulates a function with either the type GetStaticProps or GetServerSideProps, and returns a function of the same type wrapping the input function. The goal is for the wrapper to have knowledge of what it is ...

What is the Typescript compiler utilized by Visual Studio 2015 when compiling on save?

Currently using Visual Studio 2015 Update 3 with TypeScript 2 for VS installed. I have a basic ASP.NET Core MVC web application with a few simple TypeScript files. The project contains a tsconfig.json file in the root folder with "compileOnSave": true. I ...

Issue with Angular data display in template

My Ionic app with Angular is fetching data in the constructor, but I am facing difficulties displaying it in the HTML. Code component receiver: any; constructor( //.... ) { // get receiver data const receiverData = this.activatedRoute.snapsho ...

The file or directory npx-cli.js cannot be found in the specified location: ../npm/bin/

Problem Description After creating a new React project using the command below, npx create-react-app my-app --template typescript and utilizing node version v18.15.0, I attempted to set up Prettier for the project following the instructions in the Pretti ...

What is the best way to create three distinct fractions in JavaScript that cannot be simplified?

I have a specific requirement to create 3 fractions with the following conditions: The denominator remains constant The numerator must be unique and fall within the range of 1 to three times the denominator The fraction should not be reducible (e.g., 2/6 ...

Troubleshooting compilation issues when using RxJS with TypeScript

Having trouble resolving tsc errors in the code snippet below. This code is using rxjs 5.0.3 with tsc 2.1.5 import { Observable } from 'rxjs/Observable'; import { Subject } from 'rxjs/Subject'; import 'rxjs/Rx'; let subject ...

Adjust the tally of search results and modify the selection depending on the frequency of the user's searches within an array of objects

Seeking assistance with adding a new function that allows users to navigate to the next searched result. Big thanks to @ggorlen for aiding in the recursive search. https://i.stack.imgur.com/OsZOh.png I have a recursive search method that marks the first ...

What is the reason for TS expressing dissatisfaction about the use of a type instead of a type entry being provided

Below is a snippet of code for a Vue3 component that takes in an Array of Objects as a prop: <script lang="ts"> interface CorveesI { What: string, Who: string, Debit: number } export default { name: 'Corvees', props: { ...