Troubleshoot: TypeScript - Issue encountered while utilizing conditional types with enum in a generic function

I've run into a problem while working with a TypeScript function that uses conditional types based on an enum.

The enum in question:

export enum FactoryResult {
  INTERNAL_FORMALITY_CREATED_WITH_DOCS,
  INTERNAL_FORMALITY_INVALID_DOCS,
  INTERNAL_FORMALITY_MISSING_DOCS,
}

This is how the function starts:

public fromData<T extends FactoryResult>(
  data: FormalityCreationDTO,
  filesAttachments: FileAttachment[],
): {
  factoryResult: T;
  formality: T extends FactoryResult.INTERNAL_FORMALITY_MISSING_DOCS ? never : formality;
  invalidDocuments: T extends FactoryResult.INTERNAL_FORMALITY_MISSING_DOCS ? never : FileAttachment[];
} {
   if (filesAttachments.length < NumberOfFilesRequiredForCreation.TEST) {
  return {
    factoryResult: FactoryResult.INTERNAL_FORMALITY_MISSING_DOCS, // <= error
  };
...
}}

In this function, I'm using conditional types to define the types of inpiFormality and invalidDocuments based on the value of T. If T matches a specific key in the FactoryResult enum, then both properties should be of type never, indicating that they may not be returned.

The issue arises with the first condition in the function:

TS2322: Type 'FactoryResult.INTERNAL_FORMALITY_MISSING_DOCS' is not assignable to type 'T'.   'FactoryResult.INTERNAL_FORMALITY_MISSING_DOCS' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'FactoryResult'.

I would appreciate any assistance in understanding why this error occurs. Thank you for your help!

Answer №1

When it comes to assigning a conditional type in TypeScript, things can get tricky. The compiler might struggle to determine which side of the condition should be used.

However, in most cases, this complexity is unnecessary.


In this scenario, the type T is only referenced in the return type, so it cannot be inferred from the input.

Your function returns different shapes based on a runtime value (the number of items in the filesAttachments array). Therefore, it's impossible to know at compile time what will be returned. This renders a generic type parameter useless in this context.

Thus, it appears that this situation isn't truly generic; rather, it's a function that yields a discriminated union of possibilities.

To address this, define the potential return types of your function:

type MissingDocsResult = {
  factoryResult: FactoryResult.INTERNAL_FORMALITY_MISSING_DOCS
}

type OtherResult = {
  factoryResult: FactoryResult.INTERNAL_FORMALITY_CREATED_WITH_DOCS | FactoryResult.INTERNAL_FORMALITY_INVALID_DOCS
  formality: string // Define a specific type for this property
  invalidDocuments: FileAttachment[]
}

Subsequently, modify your function to adhere to these types:

class A {
  public fromData<T extends FactoryResult>(
    data: FormalityCreationDTO,
    filesAttachments: FileAttachment[],
  ): MissingDocsResult | OtherResult { // Function now returns one of these shapes
    if (filesAttachments.length < NumberOfFilesRequiredForCreation.TEST) {
      return { // Works without issues
        factoryResult: FactoryResult.INTERNAL_FORMALITY_MISSING_DOCS,
      }
    }

    return { // Also works as intended
      factoryResult: FactoryResult.INTERNAL_FORMALITY_INVALID_DOCS,
      formality: 'a specific formality here',
      invalidDocuments: filesAttachments,
    }
  }
}

Test in Playground

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

Determining the specific type of a value returned by a ReturnType

Is there a more efficient way to access the value type of a return type of a function without creating unused variables? const f = () => ({ a: 'a', b: 0 }); let atype: ReturnType<typeof f>.a; let btype: ReturnType<typeof f>.b; Any ...

Exploring the proper way to infer generic types for Redux Toolkit Slices

I've been working on a function that takes a slice factory as an argument and performs some operations on it. However, I'm facing challenges in setting up the types correctly. Below is a simple example showcasing the issue: Slice factory: expor ...

Deactivate the button if the mat-radio element is not selected

Here is my setup with a mat-radio-group and a button: <form action=""> <mat-radio-group aria-label="Select an option"> <mat-radio-button value="1">Option 1</mat-radio-button> <mat-radio-b ...

How to calculate the sum of all values in a FormArray in Angular

I am trying to retrieve the input values from each row and then calculate the sum of these rows. Here is my HTML code: <ng-container formArrayName="cap_values"> <tbody *ngFor="let item of capValues.controls; let i=index" [formGroupName]="i"& ...

Build modern web applications with Visual Studio 2015/2017 using React and TypeScript for dynamic

Has anyone successfully found a comprehensive react+typescript tutorial for a Visual Studio 2015/2017 MVC project that actually works, from beginning to end? I attempted to install the NuGet packages "Reactjs Mvc4" and "typescript", created a .tsx file, a ...

Converting a TypeScript nested dictionary into a list of strings

I am currently working with a nested dictionary and my goal is to convert it into a list of strings. For example, the initial input looks like this: var group = { '5': { '1': { '1': [1, 2, 3], ...

Encountering a 'No overload matches this call.' error when using ApexCharts with Typescript and ReactJS

As a newcomer to Typescript, I am gradually familiarizing myself with this powerful tool. After fetching the OHLCV data from coinpaprika and passing it to ApexCharts, I encountered an issue while trying to map the raw data: ERROR in src/routes/Chart.tsx:3 ...

Avoid the sudden change in page content when using Router.Navigate

When the link below is clicked, the current page jumps to the top before proceeding to the next page. <a href="javascript:void(0);" (click)="goToTicket(x.refNo, $event)">{{x.ticketTitle}}</a> component.ts goToTicket(refNo, e) { e.prev ...

Utilizing ternary operators in Angular 6 tables

I need to dynamically display certain amounts based on the comparison of two interest values. Here is the logic: <td *ngIf="subTable.flexitaxMaxPaymentDate"> subTable.flexitaxMaxInterest > subTable.IRDInterest ? {{subTable.maxAmou ...

The attribute 'data' is not found in the type 'IntrinsicAttributes & IProps'. Error code: ts(2322)

I encountered the following issue: Error: Type '{ data: never; }' is not compatible with type 'IntrinsicAttributes & IProps'. The property 'data' does not exist on the type 'IntrinsicAttributes & IProps'. import { ...

Retrieve the Ionic storage item as a string

My issue is related to the code snippet below: this.storage.get('user') Upon execution, it returns the following object: t {__zone_symbol__state: null, __zone_symbol__value: Array(0)} I am uncertain about how to handle this object. Is there ...

TS and React: Comparing View['props'] to React's ComponentProps<typeof View>

When dealing with an existing React component (referred to here as View), it appears that there are two methods to determine the type of props if it's not exported. Could someone explain the difference between these two approaches? Using lookup typ ...

Navigating concurrency problems in NodeJS when using Redis

My requirement Retrieve a token from Redis that is not already reserved for an application (its application value is not set). Assign the retrieved non-reserved token to a specific application, ensuring other threads do not get the same token for reservat ...

fix IDE error when handling responses with async/await

I find myself facing a challenging scenario involving the use of promises (then|catch) for error handling, while also awaiting code cleanliness. Here's what I'm currently dealing with: let rules:Rules = await elb.describeRules(params).promise(). ...

Global variable's value cannot be accessed outside the function in which it was inserted

I am facing an issue where I cannot access the value of var Login inside submit() function. This could possibly be due to a race condition. What could be causing this blockage in accessing the value of var Login? Here is the code snippet: class ABC { ...

The absence of class generic parameter constraints cascades down to class properties

Trying to implement TypeScript with TypeORM using a generic class has been challenging. The issue lies within my AbstractDal which takes a generic parameter that is constrained to extend IEntity. IEntity is supposed to have an id property, yet for some rea ...

Send a variable from a next.js middleware to an API request

I've been attempting to pass a middleware variable to my API pages via "req" but have encountered some issues Even after trying to send the user token to pages using "req", it consistently returns null The middleware file in question is: pages/api/u ...

Issue with Angular2: The [routerLinkActive] directive does not update when using _router.navigate

My app includes several routerLinks that I have styled using [routerLinkActive]="['active']". Everything works perfectly when I click on one of the routerLinks to navigate. However, when I try to navigate using: this._router.navigate( [ thisUrl ...

The error of testing a Node.js API arises when `jest.fn()` does not match the expected parameters using `

As a novice exploring Test-Driven Development (TDD) with NodeJS, I am currently faced with the challenge of writing a unit test for my controller implementation. Below is the snippet of my unit test: import { Request, Response, NextFunction } from "ex ...

Converting JSON Data to CSS Styles in Angular

Currently facing a challenge that has left me a bit stumped... I'm currently developing an Angular application that requires certain fields to be colored based on values stored in an XML file on the server. These colors are configured through an exter ...