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

Is there a way to use dot notation in TypeScript for a string data type?

I'm currently in the process of developing a function API with a specific format: createRoute('customers.view', { customerId: 1 }); // returns `/customers/1` However, I am facing challenges when it comes to typing the first argument. This ...

Is there a way I can replace this for loop with the array.some function?

I am looking to update the filterOutEmails function in the following class to use array.some instead of the current code. export class UsertableComponent { dataSource: MatTableDataSource<TrialUser> createTableFromServer = (data: TrialUsers[], ...

Encountering the following error message: "E11000 duplicate key error collection"

Currently, I am in the process of developing an ecommerce platform using the MERN stack combined with TypeScript. As part of this project, I am working on a feature that allows users to provide reviews for products. The goal is to limit each user to only o ...

Discover the seamless transformation of a class definition into a Vue 3 component definition utilizing the dazzling 'tc39' decorators

The proposed API in the tc39/proposal-decorators repository is significantly different from the previous decorators API. Although TypeScript 5 doesn't fully support the new API yet, it's only a matter of time before the old API becomes deprecated ...

Different tsconfigs assigned to various directories

In my project, I am using Next.js with TypeScript and Cypress for E2E tests. The challenge I am facing is configuring tsc to handle multiple configs for different folders. The tsconfig.json file in the project root for Next.js looks like this: { "c ...

Is it possible to implement a feature in Angular and Bootstrap where the toggle menu can be closed by clicking anywhere on the page, rather than just the toggle button

I'm working on an Angular project where I've implemented a navbar component. The navbar is responsive and includes a toggle button that appears when the browser window is resized. This button allows users to hide or display the menus. One issue ...

Experimenting with parallelism using TypeScript/JS

Currently, I am tackling a TS project that involves testing concurrent code and its interactions with a database, specifically focusing on idepotency. My goal is to ensure that multiple requests modifying the same resource will either apply changes correct ...

Enhance the visual appeal of your checkboxes in React Fluent UI by customizing the color of the checked mark and

I have a React application using Fluent UI. Currently, the <Checkbox/> component is displaying with its default colors and behavior like this: I want to customize the color of the checked mark and label (Green for checked mark and brown for label). ...

What is the most reliable way to create an array ensuring that all potential values come from a specific dictionary?

I am seeking a method to define the testArray so that only keys from the example dictionary can be inserted into the array. enum example { key1 = 'A', key2 = 2, key3 = '3', }; const testArray: ?? = [example.key1, example.ke ...

The where clause in the Typeorm query builder instance is not functioning properly after its common usage

When fetching data for my relations, I opted to use QueryBuilder. In order to validate certain get request parameters before the index, I established a common QueryBuilder instance as shown below. // Common Get Query const result = await this.reserva ...

Exploring the concept of the never type in TypeScript 2

Exploring the latest features in TypeScript 2.0, I came across the never type. It appears to be a clever method for defining the type of functions that do not have a return value. If I understand correctly, the never type can be assigned to any other type ...

What is the best way to access a property within a typescript object?

I'm working with the following code snippet: handleSubmit() { let search = new ProductSearch(); search = this.profileForm.value; console.log(search); console.log(search.code); } When I run the console.log(search) line, it outputs: ...

Analyzing past UTC date times results in a peculiar shift in time zones

When I receive various times in UTC from a REST application, I encounter different results. Examples include 2999-01-30T23:00:00.000Z and 1699-12-30T23:00:00.000Z. To display these times on the front end, I use new Date(date) in JavaScript to convert the ...

Encountering the following error message: "Received error: `../node_modules/electron/index.js:1:0 Module not found: Can't resolve 'fs'` while integrating next.js with electron template."

I am utilizing the electron template with next.js, and I am trying to import ipcRenderer in my pages/index.tsx file. Below is the crucial code snippet: ... import { ipcRenderer } from 'electron'; function Home() { useEffect(() => { ip ...

The parameter 'X' cannot be assigned to the argument of type 'X'

Hello there! I'm diving into Type Script for the first time with VSCode. Encountering these errors: error TS2322: Type '() => string' is not assignable to type 'string'. error TS2322: Type '() => number' is ...

Join the Observable and formControl in Angular 4 by subscribing

My goal is to display the data retrieved from FireStore in the screen fields upon loading. However, the buildForm() function is being called before subscribing to the data, resulting in the failure to populate the screen fields with the FireStore data. pe ...

Navigating through multiple pages using an Observable in Angular

After countless attempts, I still haven't been able to figure it out. Any assistance would be greatly appreciated; I recently came across Angular and RxJs. The issue I'm facing involves a service that fetches resources from various URLs of the s ...

Determine the return value of a function based on a specific conditional parameter

Is it possible for a function with a parameter of a conditional type to return conditionally based on that parameter? Explore the concept further here I am faced with a scenario where I have a function that takes one parameter, which can either be a cust ...

Enclose this within Stencil.js components

Is there a more efficient way to utilize a nested "this" in a Stencil.js component? Currently, I find myself following this approach: render() { let thisNested = this; return <Host> {this.images ? this.imagesArray.map(fu ...

"Protractor encountered an issue when navigating to the most up-to-date Angular section in our

We are in the process of upgrading our application from AngularJS to the latest version of Angular. I am currently working on writing tests that transition from the AngularJS version of the app to the admin application, which is built using the latest ver ...