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 could be causing JSON.parse to encounter errors when parsing a string array?

Within the following function, I am utilizing JSON.parse() on specific string arrays saved in window.sessionStorage. This allows me to apply methods like .map(). window.sessionStorage = { myArray1: "["805746|search|4","980093062|search|0","980113648| ...

Is there a distinction in functionality when utilizing fat arrow syntax versus traditional syntax for ES6 class methods and React?

Consider these two examples showcasing different ways to write an ES6 class method: The first example uses the non-fat arrow, or concise method syntax: class Test extends Component { handleClick() { return 'clicked' } } The second exam ...

Generating automatic generic types in Typescript without needing to explicitly declare the type

In the scenario where I have an interface containing two functions - one that returns a value, and another that uses the type of that value in the same interface - generics were initially used. However, every time a new object was created, the type had to ...

discord.js tutorial on cutting a hyperlink

i'm developing a Steam command that takes either the ID or profile link as arguments. My aim is to extract the last word. eg: https://steamcommunity.com/id/ethicalhackeryt/ here, I want to extract ethicalhackeryt or if the user directly inputs it the ...

Improving Javascript Arrays for Easier Reading

A dataset has been organized into a table format as shown below: +------+---------+----+----+----+----+-------+----------+ | Year | Subject | A | B | C | F | Total | PassRate | +------+---------+----+----+----+----+-------+----------+ | 2015 | Maths ...

Is there a way to invert the orientation of an object within a canvas?

As I was experimenting with Javascript, I attempted to implement a feature where my 'Player' character would fall down after reaching a jumpDistance of 50. The idea was to simulate a small jump-like motion for the player. While the code may not ...

Harnessing the Power of NextJS Image Component and @svgr/webpack for Seamless Integration

I have recently set up a Next.js site utilizing the @svgr/webpack library. In order to start using an SVG image with the new next/image component, I configured my next.config.js file accordingly. My next.config.js setup looks like this: module.exports = { ...

Sending information from a parent component to a nested child component in Vue.js

Currently, I am facing a challenge in passing data from a parent component all the way down to a child of the child component. I have tried using props to achieve this as discussed in this helpful thread Vue JS Pass Data From Parent To Child Of Child Of Ch ...

Executing functions in a pre-defined order with AngularJS: A step-by-step guide

In my AngularJS Controller, I have a receiver set up like this: // Broadcast Receiver $rootScope.$on('setPlayListEvent', function(event, playListData) { if($scope.someSoundsArePlaying === true) { $scope.stopAllS ...

Achieving responsive masonry layout with Bootstrap 4

I'm attempting to implement the bootstrap 4 masonry effect on my website, but I'm facing issues with card responsiveness. The page is very basic without any special effects. While the page works well when resizing the browser window, it doesn&ap ...

Encountering this issue despite confirming the presence of data on the line before! What could be the missing piece here? Error: Unable to access property 'includes' of undefined

Here is the situation.. I'm retrieving data from a database and storing it in an array of objects. These objects represent articles. I am working on implementing a filter system based on categories. The objective is to apply a filter that checks for a ...

The application's functionality is interrupted when router.navigate() is called within the .subscribe method

I am having an issue with user navigation on my application. After successfully signing in, users get redirected to the home page (/), but they are unable to navigate by clicking any links on that page. Upon further investigation, I discovered that moving ...

The ui.bootstrap.carousel component seems to be missing from the display

My Carousel is not displaying for some unknown reason. I have customized the implementation based on my project requirements which differ slightly from the standard guidelines. Despite this, it should function correctly as detailed below. By clicking on m ...

Panel floating with Bootstrap framework

I have created a unique two-column layout using Bootstrap, utilizing the col-md-6 class. The layout consists of a row with a panel at the top containing a table, a left column panel displaying a list of media items, and a right column panel containing text ...

Utilizing .html() to convert JSON data into HTML content

I have thoroughly commented the code below in my attempt to retrieve JSON data and pass it to the 'results' div in my HTML view. However, this process seems to return nothing, making it challenging to debug since no output can be displayed on the ...

Eslint in Gulp can't locate my .eslintrc configuration file

My gulp-eslint is unable to locate my .eslintrc file. I've set up a lint task as follows: gulp.task('lint', function () { gulp.src(['src/**/*.js', 'src/**/*.jsx']) .pipe(eslint()) .pipe(eslint.format()); }) The t ...

Angular 7 ERROR: The SystemJS reference is missing

In the process of developing an Angular 7 project with systemjs for dynamic module loading, I encountered an issue. Upon attempting to utilize it, I encountered the following error: ERROR ReferenceError: SystemJS is not defined Within my package.json f ...

Guide on how to initiate a file download with text area content by clicking an HTML button

I came across this code snippet on GeeksforGeeks, and it partially solves an issue I was facing. <script> function download(file, text) { //creating an invisible element var element = document.createElement('a'); ...

Using Cheerio with a Node.js bot

I am currently utilizing Cheerio to extract information from web pages in my .js files. However, I would like these files to automatically restart every 1 day to check for any new data. Instead of using setTimeout, which may not be efficient for managing ...

I am encountering an issue with my Javascript file not running due to a bigint error

I'm attempting to utilize @metaplex/js for NFT minting. Usually, my .js files function correctly, but when I execute the file, this particular error arises. bigint: Failed to load bindings, pure JS will be used (try npm run rebuild?) The meaning of ...