The process of declaring a nullable callback variable in TypeScript

Can the declaration of the resolve variable in the TypeScript code below be simplified while maintaining type safety? I am new to TypeScript, so please bear with me.

The objective is to store the promise resolver callback that is passed to the executor function so that it can be invoked later outside of it. The initial idea I came up with is

let resolve: ((v: number) => void) | null = null
. Give it a try in the TS Playground:

function timeout(ms: number): Promise<number> {
  // store the promise's resolver for later invocation
  let resolve: ((v: number) => void) | null = null; // <===
  const p = new Promise<number>(r => resolve = r);

  const start = performance.now();
  setTimeout(() => resolve!(performance.now() - start), ms);
  return p;
}

If I do not use a union type with null, TypeScript will rightfully raise an error saying that resolve might be uninitialized when called later on:

setTimeout(() => resolve(...), ms)
. Is there a more concise way to achieve this without introducing any or TypeScript errors?

To clarify, the example above may seem overly complex, and could be simplified as follows:

function timeout(ms: number): Promise<number> {
    const start = performance.now();
    return new Promise<number>(r => 
        setTimeout(() => r(performance.now() - start)));
}

However, the main focus here is on the TypeScript syntax. The actual code does require storing the promise's resolve and reject callbacks to implement the Deferred pattern.

Answer №1

To condense this code further, one approach is to eliminate the null values and delay assigning anything to resolve initially:

function timeout(ms: number): Promise<number> {
    let resolve: (v: number) => void;
    const p = new Promise<number>(r => resolve = r);

    const start = performance.now();
    setTimeout(() => resolve(performance.now() - start), ms);
    return p;
}

Although it may appear unconventional, this method is compatible with any ! assertion.

If you can immediately return the Promise, you can simplify it further by using:

function timeout(ms: number) {
    let resolve: (v: number) => void;
    return new Promise<number>(r => {
        resolve = r;
        const start = performance.now();
        setTimeout(() => resolve(performance.now() - start), ms);
    });
}

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

Despite setting the esModuleInterop flag, I am still encountering an error with default imports

My React project with TypeScript is causing some issues. In the main tsx file, the import React from 'react' line works fine. However, in my test file, I keep getting the TS1259 error. I suspect there might be a problem with my TS/Jest/Babel conf ...

The category 'Moment' cannot be assigned to the category 'Date'. The characteristic 'toDateString' is not present in the category 'Moment'

I recently integrated moment into my Angular2 application, and encountered an issue when attempting to assign the date of this week's Saturday to a variable of type date, case "weekend": this.fromDate = moment().startOf('week ...

How can I specify the parameter type as "any object value" in TypeScript?

What is the proper way to annotate a parameter type as "any value of an object"? class ExampleClass { private static readonly MODES = { DEVELOPMENT: 0, PRODUCTION: 1, TEST: 2 } // Any Value of ExampleClass.MODES c ...

You need to provide 1 type argument(s) for the Generic type ModuleWithProviders<T> in Angular 10 Swagger Codegen

Currently, I am generating Codegen proxies using . Upon implementing this in Angular 10, I encountered the following error. How can this issue be resolved? The error message reads: 'Generic type 'ModuleWithProviders' requires 1 type argume ...

Tips for organizing an array of objects that contain null properties

Here is an array that I need help with: "data": { "risks": [ { "id": "22", "name": true, "surname": 0.5, "age": 0.75, "heigth" ...

Issues with react-router-dom's <Routes> and <BrowserRouter> components

Encountering an issue with <Routes> while using react-router-dom. The code in my index.tsx file is as follows: import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './Ap ...

The package.json entry for "abc-domains" is not functioning correctly even though it is set to "latest" version

Unique Scenario Imagine there's a package called xyz-modules that I've developed. The package.json file in my project looks like this: ... "devDependencies": { "@company/xyz-modules": "latest", ... } ... After ...

Verify the legitimacy of the object

I'm encountering an issue while attempting to create a function that verifies the validity of an object. const isPeriodValid = (period: Period | null): boolean => { return period && period.start && period.end; } export interfac ...

Can a single shield protect every part of an Angular application?

I have configured my application in a way where most components are protected, but the main page "/" is still accessible to users. I am looking for a solution that would automatically redirect unauthenticated users to "/login" without having to make every ...

Getting the PlayerId after a user subscribes in OneSignal with Ionic2

Currently working on an app with Ionic2 and facing a challenge with retrieving the player id after a user subscribes in order to store it in my database. Any suggestions on how I can retrieve the unique player id of OneSignal users post-subscription? ...

Unable to determine model dependency in Nest

I encountered an issue where Nest is unable to resolve dependencies. The error message from the logger reads as follows: [Nest] 39472 - 17.08.2023, 05:45:34 ERROR [ExceptionHandler] Nest can't resolve dependencies of the UserTransactionRepository ( ...

How is it possible that there is no type error when utilizing copy with spread syntax?

When I use the map function to make a copy of an array of objects, why doesn't it throw an error when adding a new property "xxx"? This new property "xxx" is not declared in the interface. interface A{ a:number; b:string; }; let originalArray:A[] ...

Issue with knockout view - unable to remove item from view after deletion

I'm facing an issue with my code that deletes an exam from a list of exams on a page, but the deleted exam still shows up until the page is manually refreshed. This pattern works correctly on other pages, so I don't understand why it's not w ...

Hapi and Bell's attempt at authenticating with Twitter was unsuccessful

Currently, I have developed a basic backend API that requires multiple authentications. My current challenge is connecting to the Twitter API using Bell. However, instead of displaying the authentication page for the app, an error is being shown: {"statusC ...

Having difficulty mastering the redux-form component typing

I am facing an issue while trying to export my component A by utilizing redux-form for accessing the form-state, which is primarily populated by another component. During the export process, I encountered this typing error: TS2322 Type A is not assignabl ...

How to properly pass a parameter value to an Angular service when using inject.get in the constructor

After experimenting with injecting services in Angular, I encountered an issue when trying to call LogService within GlobalErrorHandler. Despite my best efforts, the code below just wouldn't work. I discovered that the problem stemmed from not passin ...

Error: Property 'xxx' is not a valid attribute for this type

Hey there! I recently converted my React Native JavaScript project into TypeScript and everything seems to be working fine. However, I'm encountering some warnings that I could use some help with. Specifically, I need assistance on how to properly pas ...

The term 'ObjectId' is typically used as a type, but in this context it is being incorrectly used as a value

I've been scouring for an answer without success. As a newcomer to both stackoverflow and typescript, I've encountered an issue while creating a Mongoose Schema. Here's a snippet of my code: import { Schema, ObjectId } from 'mongoose&a ...

Validate object containing both static and dynamic keys

I'm attempting to create a Yup validation schema for an object with the following structure: interface myObject { prop0: Date prop1: { nestedProp1: string nestedProp2: number [key: string]: string | number } } This is what I have tr ...

Having trouble with SVG Circles - Attempting to create a Speedometer design

Trying to implement a speedometer in one of the components of my Vue project, but encountering an issue. When I input 0 into my progress calculation for determining the stroke fill, it overlaps with the background circle instead of staying within its bound ...