Why is `type T1 = undefined & {}` never used in TypeScript?

After doing some research in the TypeScript documentation, I discovered that NonNullable is a type that excludes null or undefined values.

In the docs, it shows that

type NonNullable<T> = T & {};

I am curious as to why undefined & {} always results in never.

If you want to learn more about this, check out the link here: https://www.typescriptlang.org/docs/handbook/utility-types.html#nonnullabletype

Answer №1

Consider having two distinct types, named A and B. In TypeScript, the intersection type A & B encompasses values that simultaneously possess characteristics of both types A and B.

The unique empty object type {} is compatible with any structure resembling an object that can be accessed without triggering runtime errors. This implies that all object types, including most primitive types like string, align with {}. Notably, exceptions constitute only null and undefined, thus rendering {} as a representation of "anything except for null or undefined."

Hence, the theoretical type undefined & {} represents values embodying both undefined and "anything except for null or undefined." Regrettably, no such values exist, signifying that undefined & {} equates to an empty intersection symbolizing the inconceivable never type having zero attributes.

In practical terms, some instances may not immediately condense vacant intersections into never in TypeScript. Nevertheless, any idle intersection containing at least one primitive type, such as undefined, will indeed undergo such reduction by virtue of the modifications introduced in microsoft/TypeScript#31838. Consequently, undefined & {} effectively amounts to never.


Note that the NonNullable<T> utility type has undergone revision since TypeScript 4.8, now redefined as T & {}. Given that {} signifies "everything excluding null or undefined," intersecting T with {} essentially results in a refined version of T devoid of null and undefined.

Consequently, the application of NonNullable<undefined> or NonNullable<null> would yield never, as eliminating these elements from themselves leaves behind emptiness.

Answer №2

{} may seem like a strange type in Typescript, leading many style guides to caution against its use in code. Essentially, curly braces in Typescript define structural types as constraints for non-null values. For example, { a: number } represents "anything in Typescript that is non-null and has an a field with a type of number".

Expanding on this concept, {} signifies a type without any specific constraints other than being non-null. Therefore, {} encompasses all non-null values in Typescript, including objects like { a: 1 }, { b: "Some string" }, as well as numbers and strings. Even the number 42 satisfies the lack of (zero) properties enforced by the type {}.

It's crucial to note that although {} doesn't accept null or undefined, combining it with undefined results in no values within {} & undefined.

This behavior holds true only under --strictNullChecks. Without this flag, both null and undefined are included in every Typescript type, making {} & undefined essentially equivalent to just undefined, encompassing both undefined and null values.

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

Adjust the color of an SVG icon depending on its 'liked' status

In my React/TypeScript app, I have implemented an Upvote component that allows users to upvote a post or remove their upvote. The icon used for the upvote is sourced from the Grommet-Icons section of the react-icons package. When a user clicks on the icon ...

Error encountered when utilizing Meteor in conjunction with TypeScript

Currently, I am in the process of building a web application using Meteor and TypeScript within the Nitrous.io cloud development environment. After installing the TypeScript compiler, I integrated TypeScript libraries from https://github.com/meteor-typesc ...

Guide to creating a unit test for canActivate guard in Angular routing

Seeking guidance on writing a unit test for angular routing with the canActivate guard. Encountering an error when using the guard on routes, but no error is thrown without it. Would appreciate a suitable example along with an explanation. app-routing.mod ...

In TypeScript, at what level should the timeout be specified?

I'm currently working on writing a debounce function in TypeScript, but I'm feeling uncertain about the type that should be assigned to a variable used with setTimeout. This is the snippet of my code: function debounced(func: () => void, wait ...

Continue iterating using (forEach, map,...) until the object (children) has no more elements

I need to disable the active status for all elements within my object structure. Here is an example of my object: const obj = { name: 'obj1' , ative: true , children: [ { name: 'obj2' , ative: true , children: ...

In the else-branch, a type guard of "not null" results in resolving to "never."

After creating a type guard that checks for strict equality with null: function isNotNull<T> (arg: T): arg is Exclude<T, null> { return arg !== null } Testing it showed that the then-branch successfully removes null from the type. const va ...

The error "ReferenceError: window is not defined" occurs when calling client.join() due to

I am looking to create a video call application using React and Next.js with the AgoraRTC SDK. After successfully running AgoraRTC.createClient(), AgoraRTC.createStream(), and client.init(), I encountered an error when trying to execute client.join(). The ...

Using Type TTextKey to access TOption is not allowed

I'm struggling to understand why there is a complaint about return option[optionTextKey] with the error message: Type TTextKey cannot be used to index type TOption Here's the code snippet causing the issue: type Props< TTextKey, TOpti ...

The use of refs on Function components in SVG is not supported. Any attempts to access the ref will result in an

I am currently working on integrating a navigation bar component using an SVG image in Next.js. While attempting to import and utilize the SVG image, I encountered an error that I couldn't resolve. I tried using Emotion JS to create and use the SVG, ...

Typescript - Defining string value interfaces

I have a property that can only be assigned one of four specific strings. Currently, I am using a simple | to define these options. However, I want to reuse these types in other parts of my code. How can I create an interface that includes just these 4 va ...

Extending momentjs functionality with a custom method in Typescript

I am attempting to extend the momentjs prototype with a new function. In JavaScript, I achieved this with the following code: Object.getPrototypeOf(moment()).isWeekend = function() { return this.isoWeekday() >= 6; }; How can I accomplish this in T ...

What exactly occurs when a "variable is declared but its value is never read" situation arises?

I encountered the same warning multiple times while implementing this particular pattern. function test() { let value: number = 0 // The warning occurs at this line: value is declared but its value is never read value = 2 return false } My curi ...

Typescript's default string types offer a versatile approach to defining string values

Here is an example code snippet to consider: type PredefinedStrings = 'test' | 'otherTest'; interface MyObject { type: string | PredefinedStrings; } The interface MyObject has a single property called type, which can be one of the ...

Having issues with the toggle display button functionality not working properly in Angular when using click()

One of the files in my project is named server.component.ts and another is named server.component.html. This is how my server.component.ts file is structured: import { Component } from '@angular/core'; @Component({ selector: 'app-server& ...

Load Angular component on demand with necessary dependencies

Searching for an elegant solution (without resorting to private APIs) to create a widget-style dashboard. The goal is to dynamically load components based on user role. Is there a way to import a component and its dependencies included in the component&ap ...

Having trouble with typecasting in Angular 9 after receiving an HTTP response?

When initializing my component, it fetches student information from an API. Here is the ngOnInit code for component-version1: ngOnInit(): void { if(!this.student) { this.studentsService.getStudentDetail(this.id).subscribe( (response: Stu ...

Tips for updating Ref objects in React

In the process of fixing a section of my project, I'm encountering an issue where I have no control over how refs are being utilized. The Editable text elements are currently handled through refs and a state variable within the component that holds al ...

The map() function's splice operation unexpectedly removes only half of the array

I am currently working with an array that contains 146 objects, each object having its own unique id. My goal is to delete any objects from the array that do not have a matching id. I wrote a function to accomplish this task, however, it only works for hal ...

The journey of communication: uncovering the essence of @input between parent and

I'm diving into Angular and currently working on the @Input phase. Within my main app, there's a child component. Inside app.component.ts, I've declared a test variable that I wish to pass from app.component.ts to child.component.ts. // ap ...

Dealing with undefined arrays in Angular across multiple templates: Best practices

I'm currently developing a search screen for an application and I've come up with three possible outcomes for the results section. If the user hasn't searched yet, then show nothing. If the user searches and the array is empty, display "no ...