The error message indicated that a Promise<string> was expected, but instead a Promise<string|number> was received

Confusion Over Promise Type Error

How did the TypeScript compiler generate the error message displaying

Type Promise <string|number> ...
in the following scenario?

Type 'Promise<string | number>' is not assignable to type 'Promise<number>'. Type 'string | number' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'.

The code snippet that triggers this error message is shown below:

const promise: Promise<number> = Promise.resolve(100).then(n => n.toString());

Expectation vs Reality

I anticipated that

Promise.resolve(100).then(n => n.toString())
would result in a Promise<string>. When trying to assign it to
const promise: Promise<number>
, I expected TypeScript to flag a mismatch between Promise<string> and Promise<number>

However, TypeScript perplexingly introduces a string|number union and raises an issue with Promise<string|number> not being compatible with Promise<number>

Answer №1

When invoking the TypeScript call signature for the then() method of Promise objects, an interface is defined with two generic type parameters that the compiler infers during the function call.

interface Promise<T> {
  then<R = T, E = never>(
    onfulfilled?: ((value: T) => R | PromiseLike<R>) | undefined | null, 
    onrejected?: ((reason: any) => E | PromiseLike<E>) | undefined | null
  ): Promise<R | E>;
}

The first parameter R refers to the success value returned by the onfulfilled callback, while the second parameter E refers to the error value returned by the onrejected callback. The result is a promise containing a payload of the union type R | E.

By specifying the type of promise as Promise<number>, you are instructing the compiler to expect a Promise<R | E> of type Promise<number>. This triggers contextual typing, where the compiler attempts to determine E based on this constraint.

In a scenario like:

const promise: Promise<number> = Promise.resolve(100).then(n => n.toString());

The inference mechanism fails, resulting in an incompatible return type Promise<string | number> instead of the expected Promise<number>, leading to a compilation error.


This highlights the importance of understanding how type annotations impact inference and outcome when working with generics in TypeScript.

Playground link to code

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

How can I successfully transmit the entire event during the (change) event binding with ng-select in Angular 14?

I'm working on Front end Code <ng-select formControlName="constituencyId" placeholder="Select Constituency" (change)='onContituencyChanged($event)'> > &l ...

Is there a way to export a specific portion of a destructuring assignment?

const { a, ...rest } = { a: 1, b: 2, c: 3 }; If I want to export only the rest object in TypeScript, how can I achieve that? ...

What is the reason for typescript's lack of a "function" type?

As a newcomer to TypeScript, I'm puzzled as to why I am unable to define an object like this: const obj: { property1: string property2: boolean property3: function } It seems that the only workaround is to use: const obj: { property1: strin ...

Typedoc does not create documentation for modules that are imported

Whenever I generate documentation with TypeDoc, I am encountering an issue where imported files come up empty. If I add a class to the file specified in entryPoints, I get documentation for that specific class. However, the imported files show no document ...

There are zero assumptions to be made in Spec - Jasmine analyzing the callback function

I've encountered a challenge with a method that is triggered by a d3 timer. Each time the method runs, it emits an object containing several values. One of these values is meant to increase gradually over time. My goal is to create a test to verify wh ...

Guide to setting up a trigger/alert to activate every 5 minutes using Angular

limitExceed(params: any) { params.forEach((data: any) => { if (data.humidity === 100) { this.createNotification('warning', data.sensor, false); } else if (data.humidity >= 67 && data.humidity <= 99.99) { ...

Increasing a number after a delay in an Angular 2 AppComponent using TypeScript

I'm attempting to create a straightforward Angular2 Application with TypeScript. Despite its apparent simplicity, I'm struggling to achieve my desired outcome. My goal is to display a property value in the template and then update it after 1 sec ...

What could be the rationale behind the optional chaining operator not being fully compatible with a union of classes in TypeScript?

Imagine I have a combination of classes: type X = ClassA | ClassB | ClassC; Both ClassA and ClassC have a shared method called methodY. Why is it that I can't simply use the optional chaining operator to call for methodY? class ClassA { methodY ...

Needing to utilize the provide() function individually for every service in RC4

In Beta, my bootstrapping code was running smoothly as shown below: bootstrap(App, [ provide(Http, { useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, helperService: HelperService, authProvider: AuthProvider) => new CustomHt ...

A novel RxJS5 operator, resembling `.combineLatest`, yet triggers whenever an individual observable emits

I am searching for a solution to merge multiple Observables into a flattened tuple containing scalar values. This functionality is similar to .combineLatest(), but with the added feature that it should emit a new value tuple even if one of the source obser ...

Get a specific attribute of an object instead of directly accessing it

Is there a way to retrieve a specific object property in my checkForUrgentEvents method without referencing it directly? I attempted using Object.hasOwnProperty but it didn't work due to the deep nesting of the object. private checkForUrgentEvents(ur ...

Using Typescript to import Eslint with the `import/named` method

My project utilizes Eslint with the following configurations: parser: @typescript-eslint/parser 1.4.2 plugin: @typescript-eslint/eslint-plugin 1.4.2 resolver: eslint-import-resolver-typescript 1.1.1 rule extends: airbnb-base and plugin:@typescript-eslint ...

The (functionName) does not exist within the subclass as a valid function

I am currently developing an extension for a web-based text editor. However, I am facing some unexpected results due to the class hierarchy in my code. Despite attempting to relocate the "validate" function to the base class, I have not been successful in ...

How to set return types when converting an Array to a dynamic key Object in Typescript?

Can you guide me on defining the return type for this function? function mapArrayToObjByKeys(range: [string, string], keys: { start: string; end: string }) { return { [keys.start]: range[0], [keys.end]: range[1] } } For instance: mapArrayToObj ...

What are some ways to enhance this TypeScript code using Functional Programming with the FP-TS library?

i am struggling to write some typescript code using fp-ts Below are the tasks that i want the algorithm to carry out: Once a path is received from the command line, it should check if the given path exists search for all files in the directory and locat ...

The flexibility of adjusting the percentage in the ng-circle-progress feature

Currently, I am utilizing ng-cycle-progress in my Angular progress. Here is the HTML code: <circle-progress [percent]="score" [radius]="100" [outerStrokeWidth]="16" [innerStrokeWidth]="8" [outerStrokeColor]="'#78C000'" [innerStrok ...

What is the best way to retrieve the URL query parameters in a Node.js environment?

How can I retrieve URL query parameters in Node.js using TypeScript? Below is my attempted code: /** * My Server app */ import * as Http from "http"; import * as url from "url"; import { HttpServer } from "./HttpServer"; import { TaxCalculator } from ". ...

Problems with installing ambient typings

I'm having trouble installing some ambient typings on my machine. After upgrading node, it seems like the typings are no longer being found in the dt location. Here is the error message I am encountering: ~/w/r/c/src (master ⚡☡) typings search mo ...

Angular/NestJS user roles and authentication through JWT tokens

I am encountering difficulties in retrieving the user's role from the JWT token. It seems to be functioning properly for the ID but not for the role. Here is my guard: if (this.jwtService.isTokenExpired() || !this.authService.isAuthenticated()) { ...

A different approach to routing in Next.js with getServerSideProps

Let's say I have a dynamic route in my application, with the name [id] Typically, I use getServerSideProps in the pages router to validate any properties passed to the route. It usually looks something like this: export async function getServerSidePr ...