How is it that void can be assigned undefined?

According to the documentation on typescript, it states that "the one exception being that undefined is also assignable to void".

Source

Strict null checking mode specifies that null and undefined values are not within the domain of every type and can only be assigned to themselves and any (with the exception of undefined being assignable to void as well). In regular type checking mode, T and T | undefined are treated as synonymous due to undefined being considered a subtype of any T. However, in strict type checking mode, they are distinct types and only T | undefined allows for undefined values. The same principle applies to the relationship between T and T | null.

What is the reason behind this specific exception made for void?

This source does not provide an answer. Please refrain from suggesting it.

Answer №1

There is some ambiguity in the relationship between void and undefined, as they are utilized in a few contradictory ways. Typically, void is used as the return type of a function that does not yield a meaningful value. However, things become complicated when delving deeper into this concept.


For those who call a function returning void, it implies that there shouldn't be any manipulation of the return value:

declare let voidReturn: () => void;

let v = voidReturn();
v.foo; // Property 'foo' does not exist on type 'void'
v + 2; // Operator '+' cannot be applied to types 'void' and 'number

Since callers agree not to examine the return value of a void-returning function, it's permissible to substitute any function in its place, regardless of whether it returns a value or not:

voidReturn = () => 123; // okay

Check out the handbook documentation on returning void for an explanation as to why this is allowed.

From the perspective of callers of functions that return void, it's as if void resembles the unknown type. However, void existed before unknown.


On the other hand, for implementers of functions that return void, the compiler asserts that returning any defined value signifies an error:

function voidReturn2(): void {
  return 123; // error!
  // Type 'number' is not assignable to type 'void'.(2322)
}

This scenario is almost identical to assigning the function expression voidReturn = () => 123, but the former is considered erroneous. This inconsistency exists because utilizing a callback function that returns something in a context expecting a void-returning function is practical, as outlined in the aforementioned handbook. However, directly returning a defined value where a void result is expected is less useful and more indicative of an error.

Therefore, when developing a function with a return type of void, avoid returning anything:

function voidReturn3(): void { } // okay

A function lacking a return statement is equivalent to one ending with simply return;. Consequently, the compiler should also accept this, and it does:

function voidReturn4(): void {
  return;
} // okay

If a function doesn't specify a value following return, it is akin to returning undefined. The compiler should probably acknowledge this, and it does:

function voidReturn5(): void {
  return undefined;
} // okay

Thus, undefined can be assigned to void. In situations requiring a type of void, the only suitable value to use is undefined.


Despite being somewhat inconsistent and resulting in peculiar behavior, callers of void returning functions ought to disregard their return values. Yet, they have the option to hold onto a variable of type void, which can be assigned undefined but not 123:

let w = voidReturn();
w = 123; // error
w = undefined; // okay, although unusual

Feel free to explore microsoft/TypeScript#25481 and other discussions such as Why does TypeScript have both `void` and `undefined`? or why is return type `null` (or any other type) assignable to return type `void`? or Typescript: void union type.

Explore code on the Playground

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

The process of automatically formatting Typescript has transformed into an unfortunate auto-discarding action

Typescript autoformatting has become a concerning issue. Whenever I input quoted strings (" or `), the code surrounding it seems to temporarily glitch, with other strings appearing as code. This problem has recently escalated, particularly with strings li ...

I've been working on setting up a navbar in React/typescript that links to various routes, but I've hit a snag - every time I try to create a link

import React from 'react' import { Link } from 'react-router-dom' export default function NavBar() { return ( <div className='NavContainer'> <link to='/home'>Home</link> <l ...

Why is it that I have intellisense enabled for .js files but not for .ts files?

Below is the content of my package.json: { "name": "edge-node-api", "version": "1.0.0", "description": "Web API for Edge Electrons customers", "main": "api.js", "scripts": { "test": "echo \"Error: no test specified\" &am ...

Creating a backup link for a video player component in NextJs

My aim is to make sure that two video player components in a NextJS application can still access and play videos even when the application is running locally using npm run dev without an internet connection. Currently, these two components.. <HoverVi ...

What is the best way to store an audio Blob in the repository file system?

Currently, I have set up a system to record user audio through the device's microphone and can successfully download it on the same device. However, my goal now is to store this audio in my database by making an API call. How can I efficiently send th ...

Is it possible to retrieve 2 arguments within a function in a non-sequential manner?

Let's say there is a function with arguments A, B, C, D, and E. Function(A, B, C, D, E) However, not all arguments are needed all the time. For instance, only A and C are needed in some cases. Currently, I would have to call the function like this: Fu ...

The rendering process in ag-grid is resulting in the service component initialized from an event to become null

Currently, I am utilizing ag-grid and need help understanding a specific issue. In my method for preparing GridOptions, I have set up an onCellValueChanged event that triggers a service component to access the database and populate the data. However, when ...

Issue with linear Graham scan method causing failure when computing convex hull of basic polygon

It is said that the Graham scan algorithm can efficiently find the convex hull of a simple polygon in linear time without requiring the nlogn sorting step since the vertices are already effectively sorted. I have implemented the Graham scan algorithm, and ...

Is it necessary to conceal Angular navigation controls when the user is not authenticated?

In Angular, is there a standardized method for hiding controls when the user is not logged in? We already have the CanActivate guard which checks if a user can access a route. Would it be better to hide the route initially if the user is not logged in or l ...

Is there a way to expand the return type of a parent class's methods using an object

Currently, I am enhancing a class by adding a serialize method. My goal is for this new method to perform the same functionality as its parent class but with some additional keys added. export declare class Parent { serialize(): { x: number; ...

Combining multiple data types in an AJV array

Imagine you have the following defined type: type MixedArray = Array<number | string>; Now, let's say you have some sample data that needs to be validated: [ 'dfdf', 9, 0, 'sdfdsf' ] How can you create an Ajv JSONSchemeType ...

Issue with importing MomentJS globally in TypeScript

When it comes to defining global external modules in TypeScript, there is a useful option available. For instance, if you have jQuery library loaded externally, you can set up a global definition without having to include its duplicate in the TypeScript bu ...

Encountering 404 errors when reloading routes on an Angular Azure static web app

After deploying my Angular app on Azure static web app, I encountered an error. Whenever I try to redirect to certain routes, it returns a 404 error. However, if I navigate from one route to another within the app, everything works fine. I have attempted t ...

Utilize forRoot to pass configuration data

When using Angular, I encountered a challenge in passing configuration data to a custom library. Within the user's application, they are required to provide config data to my library through the forRoot method: // Importing the custom library import ...

Incorporate a typescript library into your Angular application

Recently, I added a text editor called Jodit to my angular application and faced some challenges in integrating it smoothly. The steps I followed were: npm install --save jodit Inserted "node_modules/jodit/build/jodit.min.js" in angular.json's bui ...

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? ...

Managing errors when dealing with Observables that are being replayed and have a long lifespan

StackBlitz: https://stackblitz.com/edit/angular-ivy-s8mzka I've developed an Angular template that utilizes the `async` pipe to subscribe to an Observable. This Observable is generated by: Subscription to an NgRx Store Selector (which provides sele ...

Leverage server-side data processing capabilities in NuxtJS

I am currently in the process of creating a session cookie for my user. To do this, I send a request to my backend API with the hope of receiving a token in return. Once I have obtained this token, I need to store it in a cookie to establish the user' ...

Mapping two objects of the same shape to each other recursively using TypeScript

I receive regular data from a specific source. This data consists of nested objects containing numerical values. For example: { a: 1, b: { c: 2, d: 3.1, }, } My objective is to organize this data into multiple TimeSeries objects of the same struct ...

Issue: Import statement cannot be used outside a module in Appium

Encountering the following error while working on a colleague's laptop, so it appears that there is no issue with the code itself. It could be related to my local packages but I am not entirely certain. node version: v18.20.1 npm version : 10.5.0 impo ...