What is the reason for TypeScript allowing this promise chain without any compilation errors?

Although I am still relatively new to Typescript, I find myself grappling with a particular issue that has been perplexing me. I am unsure why the following code snippet triggers a compilation error:

// An example without Promises (does not compile)
function getAnObject(): Object {
  return { value: 'Hello' };
};

function doSomethingWithAString(input: String) {
  console.log(input);
}

const result = getAnObject();
// error TS2345: Argument of type 'Object' is not assignable to parameter of type 'String' 
doSomethingWithAString(result);

On the other hand, this similar piece of code does not raise any errors:

// A similar example with Promises (compiles)
function getAnObjectAsync(): Promise<Object> {
  return Promise.resolve({ value: 'Hello' });
};

getAnObjectAsync().then(function (result: String) {
// Throws a runtime exception
console.log(result.toUpperCase());
});

This discrepancy leaves me wondering why TypeScript tolerates the fact that the onfulfilled function within the .then handler in the Promise scenario expects an input of type result: Object.

  • Have I misunderstood something?
  • Could there be a key detail about this example that eludes me?

Answer №1

The reason behind this behavior in TypeScript is due to the bivariant nature of functions' arguments.

When it comes to Promise.then, any function passed will be accepted as long as its argument is a subtype or supertype of the required type. This means that an object (Object, {}) will always pass validation. However, it is still capable of catching many incompatible types errors like trying to use { x: string } when receiving { y: number }.

This design choice has both advantages and disadvantages; personally, I believe it may not have been the best decision and could potentially change in future versions as TypeScript leans towards becoming more robust and reliable.

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

What is the best way to intentionally make a Node unit test fail when catching a Promise rejection?

When conducting unit tests with Node.js, I encountered a scenario where I needed to intentionally fail a test within a promise's catch block: doSomething() .then(...) .catch(ex => { // I need this test to fail at this point }); ...

Access nested objects in Javascript (Vue)

Struggling with a simple question as a beginner... I am dealing with an object of objects: monsters { place1: { monster1: { ... } monster2: { ... } } place2: { monster3: { ... } monster4: { ... } } } I ...

Error: The function Stripe.customers.cancel is not recognized in Stripe version 14.18.0

When executing Cypress tests that involve calling a cleanup function to remove users in Stripe, I encounter the following error: Body: { "status": 500, "message": "Error while cleaning the stripe test data", "error" ...

Fetching images using node.js via URL

I must apologize for my lack of knowledge about node.js. I am trying to read an image from a URL and resize it using sharp. Currently, my code only works for reading local images. For instance, I would like to read the following image from a URL: url= ...

nuxt-auth is experiencing difficulties retrieving token information through the refresh provider

I'm currently facing challenges with the login functionality in Nuxt 3. To handle user authentication, I've installed the package @sidebase/nuxt-auth. Below are my configurations set in the file nuxt.config.ts: auth: { globalAppMiddleware: t ...

Should one consider using the Express app.use() method within an asynchronous callback function?

Seeking advice on a recommended best practice. I recently developed an Express server that generates a JWT and sends it to the client whenever they hit an API endpoint. To maintain modularity, I separated the route handler into its own module and exporte ...

Combining Array Attributes to Create a New Property as a 'JSON String'

I'm attempting to combine the attributes of an array into a JSON-like string as a new attribute. For example: [{ { "orderNo":"1", "description":"Item 1", "note": "Note 1" }, { "orderNo":"2", "description":"Item 2", ...

Passing Selectize.js load callback to a custom function

I set up selectize.js to gather configuration options from html data attributes. One of the configurations involves specifying a js function for custom data loading (not just simple ajax loading). Everything was working smoothly until I tried running an as ...

Retrieve the route parameters and exhibit the default option in a dropdown menu using Angular 2/4/5, along with translations implemented through ngx-translate

Is there a way to extract route parameters from a URL and then display them in a drop-down menu? I've attempted some solutions using ActivatedRoute, but they are not returning the first value after the base reference. For instance, If the URL is: l ...

Tips for loading a unique class name on the initial active UI react component

Is there a way to load a class named "Landingpage" to the body tag or main container div only when the first tab/section (Overview page) is active? The tab sections are located in a child component. Any assistance would be appreciated. Click here for more ...

Encountering an issue upon pressing the 'calculate' button

Currently, I am delving into express node.js and attempting to execute a straightforward calculator code. However, whenever I click on the button, I do not receive any response, and there are no errors in my code either. I find myself a bit lost in figurin ...

IE 11 encountering issues with Date.parse returning NaN

Whenever I attempt to parse a date in Internet Explorer 11, it throws NaN at me. However, in Chrome and Firefox, I get the timestamp 1494559800000. Date.parse("5/12/2017 09:00 AM") The condition below is where things go wrong for me in IE 11. Is there an ...

What causes the cleanup function in React hooks to be triggered upon reopening a previously closed tab?

There seems to be an issue with closing a tab and then undoing that action. This causes all the cleanup functions in the component to execute, resulting in the abortion of new fetches needed to load the component. This behavior is observed only on Safari ...

What is the significance of using $timeout in order to activate a watch function?

There is an interesting phenomenon happening with my directive. It watches the height of an element that is being updated by a controller using a factory method to retrieve data. Strangely, unless I include a $timeout in that factory function, my watch doe ...

Eliminate nested object properties using an attribute in JavaScript

I am working with a nested object structured like this const data = [ { id: '1', description: 'desc 1', data : [ { id: '5', description: 'desc', number :1 }, { id: '4', description: 'descip& ...

Inject CSS into an iframe containing a JavaScript form by iterating over a collection of iframes

My task is to manipulate an iframe (chatbox) once it's loaded on a webpage. This chatbox consists of four iframes, each with a different id that changes with every page load. Since the iframe that needs manipulation is always the last one in the list, ...

Is it possible to declare language features in Typescript? For example, changing `!variable` to `no variable`

Can Typescript language features be declared within the app's source code? I want to enhance code clarity by implementing a small feature. Modified Null Test if (no userDetails) { // handle null } This new null test syntax is a little more conc ...

Is there a way to disable default tooltips from appearing when hovering over SVG elements?

Looking for a way to display an interactive SVG image on an HTML page without default tooltips interfering. While I'm not well-versed in javascript/jQuery, I've managed to implement customized tooltips using PowerTip plugin. However, these custom ...

Guide on enabling users to input slide number and URL address to load content using Ajax

Is there a way to customize the number of slides in a slider and choose which content is loaded into each slide using AJAX calls in jQuery? Currently, my slider uses the jQuery .load() method to dynamically load content into each slide when it becomes vis ...

NodeJS experiencing a hitch in the image upload process

I am currently working on a Node code snippet that is used for uploading images. The images I am dealing with have sizes ranging from 10 to 200K, so they are relatively small in size. However, the issue I am facing is that Node seems to get stuck process ...