As a quirk of TypeScript, it does not allow for returning a Tuple directly and instead interprets it as an Array

I need assistance with adding type-safe return to a general function created by a previous developer. Here is the current syntax:

export function to(promise:Promise<any>) {  
  return promise
    .then(data => [null, data])
    .catch(err =>  [err, null]);
 }

This function simply takes in a promise and returns a new promise with an output type of a tuple

[Error|null, <The First Promise's Return Type>|null]
. This means that the first value will be an error if there is one (otherwise null), and the second value will be the result of the initial promise (otherwise null). Usage example:

const [ err, result ] = await to(/*<API Call>*/);
if (err) {
    setError(err);
    // ...
} else if (result) {
    processApiResult(result);
    // ...
}

Currently, I am aware that there is an issue ((T|null)[] should not represent "an array of either of those types", but rather "a tuple of those types with a specific order"), but I have been struggling to find a solution.

export function to<T>(promise:Promise<T>):Promise<(T|null)[]|[Error, null]> {  
  return promise
    .then(data => [null, data])
    .catch(err => [err as Error, null]);
 }
 
const [ err, result ] = await to(api.changePassword(username, password));  
// const error : string | Error | null
// const result : string | null

The expected type for the first parameter should be Error | null (not | string), while the second parameter is correctly defined as string | null.

Answer №1

If you're confident that the tuples generated by to() won't be altered, you can apply const assertions to type this function.

export function to<T>(promise:Promise<T>):Promise<readonly [Error | null, T | null]>  {  
  return promise
    .then(data => [null, data] as const)
    .catch(err => [err as Error, null] as const);
}

const [ err, result ] = await to(api.changePassword(username, password));  
// err: Error | null
// result: string | null

This approach works because as const will convert the array literals' types into readonly tuples.

If there's a need for the tuples not to be read-only, an alternative method is available:

export function to<T>(promise:Promise<T>):Promise<[Error | null, T | null]>  {  
  return promise
    .then(data => [null, data] as [null, T])
    .catch(err => [err as Error, null] as [Error, null]);
}

const [ err, result ] = await to(api.changePassword(username, password));  
// err: Error | null
// result: string | null

In either scenario, it is crucial to communicate to the compiler that the values returned by to() are fixed-sized tuples, not arrays.

Answer №2

function convertPromise<T>(promise:Promise<T>):Promise<[Error|null,T|null]> {
    return promise
        .then((data):[null,T] => ([null, data]))
        .catch((err) =>( [err, null]));
}

async function asyncFunc() {
    const [ error, result ] = await convertPromise<string>(new Promise(resolve => resolve));
    console.log(error,result)
}

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

Using TypeScript to specify a limited set of required fields

Can a custom type constraint be created to ensure that a type includes certain non-optional keys from an object, but not all keys? For instance: class Bar { key1: number key2: Object key3: <another type> } const Y = { key1: 'foo' ...

Mocking is not working for request scoped injection

I'm encountering an issue with mocking the return value of a provider, as it seems to be clearing out the mock unexpectedly. Module1.ts @Module({ providers: [Service1], exports: [Service1], }) export class Module1 {} Service1.ts @Injectable({ ...

An unusual problem encountered while working with NextJS and NextAuth

In my NextJS authentication setup, I am using a custom token provider/service as outlined in this guide. The code structure is as follows: async function refreshAccessToken(authToken: AuthToken) { try { const tokenResponse = await AuthApi.refre ...

Utilizing typescript to isolate specific functionality from a class without extending it

Imagine a scenario where I have a class with different areas of functionality: export class TreeTable extends someOtherClass { constructor(){ super.constructor(); } //========= area 1 of functionality ==== itemRightClick(){this.contex ...

Out of the blue, I encountered an issue while trying to install Express in node.js using Types

Encountered a failure while attempting to install Express with node.js in Typescript. Received the following warning: https://i.sstatic.net/XcrGX.png Performed npm initialization, started index.js, created tsconfig.json, and installed ts-node. The comman ...

Error: Unhandled promise rejection - The function get is not part of this.categoryMap

I am facing an issue with calling functions of the Map (get, set, keys, etc) within my function. The map I am working with is returned from a firebase query. Here's a snippet of my code: categoryMap = new Map<Number, String>(); //called onInit ...

Implementing redux-persist with redux toolkit using TypeScript

Currently, I have been utilizing Redux Persist in my next js application but now I am interested in incorporating redux toolkit with TypeScript. While I have managed to grasp the syntax for implementing redux-persist in redux toolkit, I am struggling to ...

A loop in JavaScript/TypeScript that runs precisely once every minute

Here is a snippet of my code: async run(minutesToRun: number): Promise<void> { await authenticate(); await this.stock.fillArray(); await subscribeToInstrument(this, this.orderBookId); await subscribeToOrderbook(this, this.orderBookId ...

Is it not possible to call this authentication expression in a Typescript file when using Next JS?

I am currently developing a sign-in method for my Next.js application and I have been referring to the GitHub repository's recommended documentation. However, upon reaching the authentication folder step, I encountered an error regarding the sign-in ...

deliver a precise observable

Recently, I spent hours following a tutorial on jwt refresh tokens, only to discover that the code was outdated and some changes were required. As a result, I created an interceptor which encountered an issue with the Observable component, leaving me unsur ...

The error message "Unable to access property 'open' of an undefined menu" is being displayed in a TypeScript code

I am facing an issue with the action in my menu. For this project, I am using a material menu and icons. The main menu code appears as follows: <mat-menu #rootMenu="matMenu" [overlapTrigger]="false"> <ng-template matMenuContent let-element="ele ...

Confirming changes to checkbox values in Angular 2 prior to updating

My current challenge involves implementing a confirmation dialog in my application, and I'm feeling a bit unsure about the logic behind it. UserDetailsComponent.ts import { Component, OnInit, OnDestroy, ViewChild, Input, OnChanges, SimpleChange } f ...

Having trouble managing TypeScript in conjunction with React and Redux

As a newcomer to TypeScript, I find myself struggling to grasp the concepts and know where to start or stop. While there are abundant resources available online, I have not been able to effectively utilize them in my project. I am hopeful for some guidance ...

Using Angular: A guide to setting individual values for select dropdowns with form controls

I am working on a project that involves organizing food items into categories. Each item has a corresponding table entry, with a field indicating which category it belongs to. The category is represented by a Guid but displayed in a user-friendly format. C ...

Which rxjs operator should be used when dealing with nested subscriptions in the presence of an if statement?

In my Angular/Typescript project, I am dealing with 2 subscriptions. Each subscription is subscribing to its own observable A and B, which are located outside the component in the service file. Sometimes, when A changes, B may or may not change based on c ...

How can we leverage mapped types in TypeScript to eliminate properties and promisify methods?

Below is the provided code snippet: class A { x = 0; y = 0; visible = false; render() { return 1; } } type RemoveProperties<T> = { readonly [P in keyof T]: T[P] extends Function ? T[P] : never//; }; type JustMethodKe ...

What is the best way to merge the results of several runs of an observable function

When working with Firestore, I need to retrieve multiple documents, each with a unique sourceAddressValue. This means for a list of N strings, I may need to fetch N documents. I attempted the following approach: getLocationAddresses(addresses: string[]) { ...

Can a generic type be utilized to instantiate an object?

In my code, I have a class named Entity as shown below: class Entity { constructor(readonly someValue: string) {} someFunction() {} } Now, I am trying to create a class that will handle these entities and be able to create instances of them. In or ...

How can TypeScript be forced to output a specific data type?

I've created a generic "fetcher" function that is designed to handle different types of entities. However, I'm encountering an issue where TypeScript is inferring the return type based on all possible conditions within the function. Is there a w ...

What steps can be taken to resolve the error message "Using 'null' as an index type is not allowed."?

In my TypeScript code, I have a variable called lang declared as a string type value, and a variable called direction declared as an object with two elements. I also have a function that is supposed to return the value of the direction object based on th ...