What causes the difference in inference for unspecified generics between a simple function call and a null-coalescing operator in TypeScript?

What causes the different types of a and b in the given code snippet?

function empty<T>() { return [] as T[] }

const defEmpty = empty()

function test1(abc: number[]|null) {
  const a = abc ?? defEmpty
  const b = abc ?? empty()
}
 

Upon testing on the playground, it displays that a: unknown[] and b: number[]. This outcome is unexpected, as both were supposed to be of type unknown[].

Answer №1

The explicit generic type was not provided in the call to empty() here:

const b = abc ?? empty()

However, Typescript can deduce that type from the expression - it recognizes that abc is of type number[] | null, so it infers that the type parameter for the empty call is number (this information can be seen by hovering over empty() in the playground). Therefore, your line essentially becomes:

const b = abc ?? empty<number>();

Hence, 'b' is also of type number[]. It's important to note that omitting the generic type parameter does not default to unknown.

Regarding how exactly type inference operates - there isn't a strict specification available to refer to. The latest version has been archived and no longer updated. There have been some changes made to the type inference rules compared to this archived version. Therefore, the most reliable source of information would be the official documentation, which provides somewhat vague explanations. The section relevant to this topic is called "Contextual Typing," where it broadly explains that Typescript can infer generic type parameters based on context in many scenarios, without detailing exactly how.

In this specific scenario, however, the situation appears quite straightforward. The known type on the left side of the ?? expression allows for the same type to be used on the right side with the generic type parameter omitted.

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

Make sure that every component in create-react-app includes an import for react so that it can be properly

Currently, I am working on a TypeScript project based on create-react-app which serves as the foundation for a React component that I plan to release as a standalone package. However, when using this package externally, I need to ensure that import React ...

Having difficulty storing duplicate requests that are crucial for various services/components

Currently, I am tackling a project that involves displaying multiple sets of data to the user. Each set requires several requests to be made to the backend. Specifically, for the UserDetails dataset, I must query the getUser and getSigns endpoints. However ...

How can you connect a property to the output of a method in Vue.js when working with TypeScript and vue-property-decorator?

I'm working with a TypeScript single file vue component. I've encountered an issue where the template does not display the values returned by certain component methods. Here's a snippet of the template: <div class="order-items"> ...

Organizing the AuthGuard(canActivate) and AuthService code in Angular 2

After working on my current code, I have encountered an issue when routing to a page with the canActivate method. I was able to retrieve authentication data from the server using the following setup auth.guard.ts (version 1) import { CanActivate, Activat ...

Adding an arrow to a Material UI popover similar to a Tooltip

Can an Arrow be added to the Popover similar to the one in the ToolTip? https://i.stack.imgur.com/syWfg.png https://i.stack.imgur.com/4vBpC.png Is it possible to include an Arrow in the design of the Popover? ...

Error with React Query Mutation and TypeScript: The argument '{ surgeryID: any; stageTitle: any; }' cannot be assigned to a parameter of type 'void'

Utilizing react-query for fetching and posting data to my database on supabase has been really helpful. I took the initiative to create a custom hook specifically for adding records using react-query: export function useAddSurgeryStage() { const { mutate ...

Resolving the issue of missing properties from type in a generic object - A step-by-step guide

Imagine a scenario where there is a library that exposes a `run` function as shown below: runner.ts export type Parameters = { [key: string]: string }; type runner = (args: Parameters) => void; export default function run(fn: runner, params: Parameter ...

Tips for eliminating nested switchMaps with early returns

In my project, I have implemented 3 different endpoints that return upcoming, current, and past events. The requirement is to display only the event that is the farthest in the future without making unnecessary calls to all endpoints at once. To achieve th ...

There is a clash between the webpack-dev-server package and its subdependency, the http-proxy-middleware

Awhile back, I integrated webpack-dev-server v3.11.0 into my project, which - upon recent inspection - relies on http-proxy-middleware v0.19.1 as a dependency. Everything was running smoothly until I separately installed the http-proxy-middleware package a ...

The KeyValuePair<string, Date> type in Typescript cannot be assigned to the KeyValuePair<number, string> type

I encountered the following issue: An error occurred stating that Type 'KeyValuePair<string, Date>' is not assignable to type 'KeyValuePair<number, string>'. Also, it mentioned that Type 'string' is not assignab ...

The submit button seems to be unresponsive or unreactive

As a newcomer to Angular 2 and Typescript, I am in the process of building a web application. I have created several input fields and, following user submission via a button, I want to log the inputs to the console. However, it seems like my button is not ...

Create a d.ts file in JavaScript that includes a default function and a named export

While working on writing a d.ts file for worker-farm (https://github.com/rvagg/node-worker-farm), I encountered an issue. The way worker-farm handles module.exports is as follows: module.exports = farm module.exports.end = end When trying to replica ...

Entering _this

I am encountering an issue with my typescript file where it is failing TSLint. I need some help resolving this problem. The structure of the object in question is as follows: export default class Container extends Vue { // methods doSomething() { ...

What is causing the undefined value for the http used in this function?

My Code Component import { Component, OnInit } from '@angular/core'; import { Http } from '@angular/http'; @Component({ selector: 'app-root', template: '<button id="testBtn"></button>' }) export c ...

Guide on saving a PDF file after receiving a binary response using axios

Is there a way to save a PDF file from a binary response received through an axios get request? When making the request, I include the following headers: const config: AxiosRequestConfig = { headers: { Accept: 'application/pdf', respon ...

What is the significance of parentheses when used in a type definition?

The index.d.ts file in React contains an interface definition that includes the following code snippet. Can you explain the significance of the third line shown below? (props: P & { children?: ReactNode }, context?: any): ReactElement<any> | nu ...

Warning: Google Map API alert for outdated Marker Class

Working on an application using the Google Maps TypeScript API, I came across a warning message when launching the app -> As of February 21, 2024, google.maps.Marker will no longer be available. Instead, developers are advised to use google.maps.marke ...

JavaScript heap running out of memory after upgrading from Angular 11 to versions 12, 13, or 14

I need assistance with resolving a JS heap out of memory issue that has been occurring when trying to start the local server ever since migrating from Angular 11 to Angular 12 (or 13 or 14, all versions tested with the same problem). This occurs during th ...

What could be causing the lack of Tailwind CSS intellisense in a Next.js app with TypeScript?

Check out my tailwind.config.ts file I've been trying to figure it out by watching YouTube tutorials, but nothing seems to be working. Even with the tailwind.config.ts file in my Next.js app, it still isn't functioning properly. Perhaps there&ap ...

Mongodb Dynamic Variable Matching

I am facing an issue with passing a dynamic BSON variable to match in MongoDB. Here is my attempted solutions: var query = "\"info.name\": \"ABC\""; and var query = { info: { name: "ABC" } } However, neither of thes ...