Initialization of an empty array in Typescript

My promises array is structured as follows:

export type PromisesArray = [
  Promise<IApplicant> | null,
  Promise<ICampaign | ICampaignLight> | null,
  Promise<IApplication[]> | null,
  Promise<IComment[]> | null,
  Promise<{ status: number; message: IActionTag[] }> | null,
  Promise<IHistoryEntry[]> | null,
  Promise<IDocs> | null,
  Promise<IForm> | null,
];

I aim to initialize it with an empty value like

const promisesArray = <PromisesArray>[]
.

But, I encounter this error message:

The conversion of type '[]' to 'PromisesArray' may be a mistake due to insufficient overlap between the types. To proceed intentionally, first convert the expression to 'unknown'.
  Type '[]' lacks properties present in '[Promise<IApplicant>, Promise<ICampaign | ICampaignLight>, Promise<IApplication[]>, ...and more.]': 0, 1, 2, 3, and more.ts(2352)

Later on, when I attempt to add an item to the array:

If (this._printOptions[EPrintOption.Tags]) {
  const applicantActionsTagsPromise = ApplicantService.getActions(this._applicantId);
  promisesArray.push(applicantActionsTagsPromise); // This line triggers the error
} else {
  promisesArray.push(null);
}

This results in the following error:

The argument 'Promise<IActionTag[]>' cannot be assigned to the parameter 'Promise<IApplicant> | Promise<ICampaign | ICampaignLight> | Promise<IApplication[]> | ...and more...'.
  Type 'Promise<IActionTag[]>' is incompatible with type 'Promise<IApplicant>'.
    Certain properties are missing from 'IActionTag[]' compared to 'IApplicant': address, advertiseid, applicantid, birthdate, and others.ts(2345)

I am seeking a resolution for this issue without resorting to using the 'any' type.

Answer №1

To resolve your issue in both scenarios, the complexity arises from the fact that you're adding one element at a time to the array instead of assigning the entire array altogether. If you were to modify your code so that you assign the complete Promise array at once, then you could revert back to your original definition seamlessly:

declare type PromisesArray = []
  | [
    Promise<IApplicant> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null,
    Promise<IComment[]> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null,
    Promise<IComment[]> | null,
    Promise<{ status: number; message: IActionTag[] }> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null,
    Promise<IComment[]> | null,
    Promise<{ status: number; message: IActionTag[] }> | null,
    Promise<IHistoryEntry[]> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null,
    Promise<IComment[]> | null,
    Promise<{ status: number; message: IActionTag[] }> | null,
    Promise<IHistoryEntry[]> | null,
    Promise<IDocs> | null
  ]
  | [
    Promise<IApplicant> | null,
    Promise<ICampaign | ICampaignLight> | null,
    Promise<IApplication[]> | null,
    Promise<IComment[]> | null,
    Promise<{ status: number; message: IActionTag[] }> | null,
    Promise<IHistoryEntry[]> | null,
    Promise<IDocs> | null,
    Promise<IForm> | null
  ]
;

Answer №2

There are a couple of concerns I want to address regarding this solution:

Firstly, the issue lies in the fact that your type specifies an array that can contain null values, but not undefined values.

To set the correct initial value, it is recommended to use:

const promisesArray = <PromisesArray>[null, null, null, null, null, null, null, null];

Secondly, Array.push does not keep track of the current index, thus making it challenging to infer the proper type for each array element.

An alternative approach would be to define the entire array at once using as const. This allows TypeScript to interpret your array as a tuple, where each element has its own specific type instead of combining all types into one union.

enum Tags {
    String,
    Number,
    Boolean
}

type Options = {
    [key in Tags]?: boolean;
};

const options: Options = {
    [Tags.String]: true,
    [Tags.Boolean]: true
};

// Use `as const` to determine the array type as a tuple.
const promiseArray1 = [
    options[Tags.Number] ? Promise.resolve(5) : null,
    options[Tags.Boolean] ? Promise.resolve(true) : null,
    options[Tags.String] ? Promise.resolve('string') : null
] as const;

// Alternatively, declare the type as previously done.
type PromiseArray = [
    Promise<number> | null,
    Promise<boolean> | null,
    Promise<string> | null
];
const promiseArray2: PromiseArray = [
    options[Tags.Number] ? Promise.resolve(5) : null,
    options[Tags.Boolean] ? Promise.resolve(true) : null,
    options[Tags.String] ? Promise.resolve('string') : null
];

Playground

Answer №3

If you find yourself creating an array type with very specific types in each index, perhaps utilizing an Array is not the most efficient choice after all. It appears that defining a type with named properties could be more advantageous:

interface CustomPromisesBundle {
  promiseIUser?: Promise<IUser>;
  promiseIProduct?: Promise<IProduct>;
  ...
}

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

What is the purpose of requiring the explicit invocation of app.listen(port) to enable express-ws to function properly?

I've recently started exploring NodeJS Express and came across the official tutorial from express-ws for setting up websockets in a simple project generated using npx express-generator. While following the tutorial, I noticed that in the app.js file, ...

Visual Studio Code unable to locate source maps for typescript debugging

Looking for some help debugging a basic Hello World TypeScript file. Whenever I try to set a breakpoint, it seems like VS Code is having trouble locating the source map, even though it's saved in the same directory. I'm using Chrome as my browser ...

Tips for setting a value from an AJAX-created element into a concealed form field

There is a div that contains a button. When the button is clicked, a form appears. The div's id is then assigned to a hidden field within the form. This functionality works for the divs that are present on the page when it initially loads, but it does ...

The value of a string in jQuery turns undefined once it is used as an argument

Hello there, Currently, I am working on a personal project involving NodeJS and Electron. The project is a basic text editor as of now. However, I am facing an issue when attempting to pass the value of a text-area to a function before saving it to a file ...

A guide on parsing a nested JSON file with ExtJS 4

Here is the content of my JSON file named "jobInfo.json": { "job": { "id": 1, "name": "Job 1", "description": "bla bla bla", "locations": { "type": "FeatureCollection", "features": [{ "id": 1, "t ...

"Jquery's .append function may sometimes display as undefined when

$("#clckjson").click(function() { $(document).ready(function() { $.getJSON("fuelj.json", function(data) { $(data).each(function(i, item) { console.log(item.stationID); var $table = $('<table>'); $table.a ...

Error encountered during Jasmine unit testing for the ng-redux @select directive

Here is a snippet from my component.ts file: import { Component, OnInit } from '@angular/core'; import { select } from 'ng2-redux'; import { Observable } from 'rxjs/Observable'; import { PersonalDetailsComponent } from ' ...

Transforming a function into an array in TypeScript

I attempted to use the map() function on a dataURL array obtained from the usePersonList() hook, but I am struggling to convert my function to an array in order to avoid errors when clicking a button. import Axios from "axios"; import React, { us ...

TypeScript combines strong typing for arrays into a unified array of objects

I developed a JavaScript function that can merge multiple arrays into an array of objects based on provided key names. Here’s an example: const mergeArraysToSeries = (arrs, keys) => { const merged = []; for (let dataIndex = 0; dataIndex < arrs ...

The response from getStaticProps in Next.js is not valid

While following the Next.js documentation, I attempted to retrieve data from a local server but encountered an error message: FetchError: invalid json response body at http://localhost:3000/agency/all reason: Unexpected token < in JSON at position 0 ...

Deactivate the form element when a user selects another button

I am facing an issue with two buttons that are linked to the same modal form. Here is the code snippet for the form: <form name="addUser" ng-submit="(addUser.$valid) ? add() : '';"> <div class="form-group has-feedback" ng-class="ad ...

Checking if the iframe location has been modified using Jquery

Looking to determine if the location of an iframe has been modified. function checkLocation() { setInterval(function(){alert("Hello")},3000); if (document.getElementById("myiframe").src = 'http://www.constant-creative.com/login';) { } ...

With the use of discreet JavaScript, the parameter is not empty; instead, it contains values

Previously, my JavaScript code was functioning correctly when it was within the same page as my cshtml file: function SaveEntity() { // more code here alert(entity.FirstName); /* this shows that entity's properties have values */ $.post( ...

Tips for using jQuery to slowly change a CSS property to "auto"

I've encountered a situation where I have an element styled with position:fixed, and bottom: auto;. When I apply the command .animate({bottom : '10%'});, it smoothly slides to the specified position. However, when I try to set it back to its ...

Node is looking for a callback function, but instead received something that is undefined

When attempting to build a basic CRUD app in node js, an issue arises with the error message "Route.get() requires a callback function but got a [object Undefined]" specifically on the router.get("/:id", userController.getUser); line. Routes.js const expr ...

Using ES6 to generate objects within other objects

Dealing with data from a local API can be challenging, especially when you have limited control over the incoming data. However, I am looking to transform the data post my API call using a custom function. This is my current approach transformArray = () ...

Errors with the email composer in Ionic 3 displaying "plugin_not_installed" issue

Currently utilizing this feature within my Ionic 3 application. The plugin has been successfully installed, and the cordova-plugin-email-composer folder is present in the plugins directory. Despite multiple attempts of uninstalling and reinstalling, an err ...

Instructions on how to insert a new row into Datatables following the successful submission of a form via AJAX请求

Could someone please provide guidance on how to insert a new row into an existing datatable after a successful AJAX request? Here is the code I am currently using: $(document).ready(()=>{ $.ajax({ url: 'http://localhost:3000/api/post/getUserDat ...

Unveiling the Power of KnockoutJS: Displaying HTML Content and Populating

I am trying to achieve a unique effect using KnockoutJS. Let's consider a basic model: var Item = function () { var self = this; self.title = ko.observable(""); }; In addition, I have a ViewModel: var ItemList = function () { var self = ...

Validation for prototype malfunctioning

I am currently using Prototype.js to implement form validation on my website. One of the fields requires an ajax request to a PHP file for validation purposes. The PHP file will return '1' if the value is valid and '0' if it is not. Des ...