Comparing TypeScript's `return;` with `return undefined;`: which is better?

I encountered a strange behavior that is puzzling to me, and I'm not sure if there's a logical explanation for it.

In TypeScript, the following code works perfectly:

type UndefinedFunction = () => undefined;

let uf: UndefinedFunction = function() {
    return; // no errors
}

This makes sense to me because in JavaScript, when a function uses return; without a value, the returned value is undefined.

However, the following code results in an error:

type MaybeUndefinedFunction = () => string | undefined;

let muf: MaybeUndefinedFunction = function() {
    return; // error
}

An error message is displayed stating that

Type '() => void' is not assignable to type 'maybeUndefinedFunction'. Type 'void' is not assignable to type 'string | undefined'

This inconsistency confuses me. Although I found information regarding void vs undefined on Stack Overflow, it doesn't explain why return; is now identified as void instead of

undefined</code, especially when it worked fine in the previous example.</p>
<p>To resolve the error, I can use <code>return undefined;
, but I am curious about why this workaround is necessary since both return; and return undefined; should have the same outcome.

Interestingly, the same issue occurs when not returning anything at all - it works in the first case but produces an error in the second, despite both complying with the expected undefined return value.

If you'd like to see the error in action, check out this playground link: Playground Link

Answer №1

Throughout its history, TypeScript considered functions without an explicit return value as having a void return type, indicating that "nobody knows what this function returns" rather than specifically returning undefined. Prior to the introduction of easier implicit returns for functions returning undefined in TypeScript 5.1 as seen in microsoft/TypeScript#53607, both examples provided would have caused errors:

let uf: UndefinedFunction = function () { return; } // error!
//  ~~ <-- Type '() => void' is not assignable to type 'UndefinedFunction'.

Playground link showing code in TS 5.0.4

However, uf no longer produces an error following the aforementioned pull request, which states:

  • Functions with an explicitly specified return type of undefined are not required to have return statements (similar to functions with a return type of void or any). This exemption does not apply to functions with union return types containing undefined

This adjustment only applies to functions with a direct return type of undefined, excluding unions that include undefined like string | undefined. Therefore, muf still triggers an error:

let muf: MaybeUndefinedFunction = function () { return; }
//  ~~~ <-- Type '() => void' is not assignable to type 'MaybeUndefinedFunction'.

This addresses the initial question. It's worth considering why union types are not supported, a topic left unanswered in a discussion on microsoft/TypeScript#53607. The distinction between the two cases presented stems from how microsoft/TypeScript#53607 was implemented.

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

Typescript - Error in Parsing: Expecting an expression

I am currently working with Vue and TypeScript and have encountered a problem. How can I resolve it? Here is the code snippet in question: private setTitle(systemConfig: any) { const systemConfigParse; let obj; systemConfigParse = JSON.parse(sy ...

Imitate dependencies using Mocha and Typescript

In my typescript project, I am using mocha. Let's consider two modules: // http.ts export class Http { } // app.ts import Http from './http'; export class App { } I want to know how to mock the Http module while testing the App. The te ...

Testing Next.js's getServerSideProps function with Jest: A Step-by-Step Guide

I want to conduct Jest and Enzyme tests on the Next.js getServerSideProps function. This function is structured as follows: export const getServerSideProps: GetServerSideProps = async (context) => { const id = context?.params?.id; const businessName ...

What is the best way to align a title above menu items within a Material UI app bar when using TypeScript and React?

Check out my current app bar design: app bar image Here is the inspiration for the app bar layout I'm aiming for (title above menu items): inspiration app bar goal This snippet showcases my code: import * as React from 'react'; // More cod ...

TS2365: The '!== 'operator is not compatible with the types ""("" and "")""

function myFunction(identifier: string) { identifier = "("; }; let identifier: string = ")"; if (identifier !== '(') throw "Expected '(' in function"; myFunction(identifier); if (identifier !== ')') throw "Expected &a ...

Using Typescript and React to retrieve the type of a variable based on its defined type

Just getting started with Typescript and could use some guidance. Currently, I'm using React to develop a table component with the help of this library: Let's say there's a service that retrieves data: const { data, error, loading, refetc ...

"What could be causing my React application to enter a never-ending re-rendering cycle when I incorporate

Currently, I'm working on a code to update the content of a previous post with image URLs received from the server. However, I'm facing issues with excessive re-renders due to my coding approach. Specifically, when converting the image URLs into ...

What are the steps to implement the `serialport` library in `deno`?

After tinkering with Deno to extract readings from an Arduino, I encountered a roadblock when it came to using the serialport library correctly. Here is what I attempted: According to a post, packages from pika.dev should work. However, when trying to use ...

Issue with the proper functionality of the this.formGroup.updateValueAndValidity() method in Angular 6

Currently, I am facing an issue where I need to add or remove validators in a formGroup's controls based on certain conditions. When I try to update the validators using `formGroup.updateValueAndValidity()` for the entire form, it does not seem to wor ...

Issue with detecting window resize event in Angular 7 service

I have a unique service that utilizes a ReplaySubject variable for components, but strangely the WindowResize event isn't triggering. import { Injectable, HostListener } from '@angular/core'; import { ReplaySubject } from 'rxjs'; ...

Incorrectly selecting an overload in a Typescript partial interface can lead to errors

My attempt to define an overload for my function using a Partial interface overloading is causing typescript to select the incorrect overload interface Args { _id: string; name: string; } interface Result { _id: string; name: string; } function my ...

Retrieve the Document ID from Firebase

I'm currently exploring the functionality of Firebase and enhancing my workflow with "react-firebase-hooks". Is there a way for me to retrieve both the doc id and doc data simultaneously and pass them as props? Currently, I am only able to access the ...

Modify the height of React Cards without implementing collapse functionality

Currently, I am in the process of developing a web interface that displays various processes and services. The information is presented in React cards that support expand/collapse functionality. However, I am facing an issue where expanding one card affect ...

Collect the GET parameters as an array of strings when there is only one value

How can I properly pass a string array as a parameter for a GET call? // Passing one value param: filters=Something value: filters: 'Something' // Passing multiple values param: filters=Something&filters=Something else value: filters: [ &ap ...

Guide to summing the values in an input box with TypeScript

https://i.stack.imgur.com/ezzVQ.png I am trying to calculate the total value of apple, orange, and mango and display it. Below is the code I have attempted: <div class="row col-12 " ngModelGroup="cntMap"> <div class="form-group col-6"> ...

How can I encode and decode a base64 string using AngularJS1 and TypeScript?

I am currently working with Angular1 using TypeScript and I have a question that needs some clarification. Within the environment that I am operating in, is there a method available to encode and decode a string in base64? Despite conducting extensive re ...

Using Angular to display asynchronous data with ngIf and observables

In cases where the data is not ready, I prefer to display a loader without sending multiple requests. To achieve this, I utilize the as operator for request reuse. <div class="loading-overlay" *ngIf="this.indicatorService.loadingIndicators[this?.indic ...

Exploring Angular 17's unique approach to structuring standalone components

Is something wrong with my code if I can only see the footer, header, and side-nav components on localhost? How can I fix this? app.component.html <div class="container-fluid"> <div class="row"> <div class=&q ...

Struggling with the Transition from Google Sign-In

Having difficulty transitioning from Google Sign-In. "{error: 'idpiframe_initialization_failed', details: 'You have created a new client application that use…i/web/guides/gis-migration) for more information.'}" How do I u ...

Is there a way to incorporate an "else" condition in a TypeScript implementation?

I am trying to add a condition for when there are no references, I want to display the message no data is available. Currently, I am working with ReactJS and TypeScript. How can I implement this check? <div className="overview-text"> < ...