An element can be either an object or an array of objects

Is there a way to define a type/interface that can handle both objects and arrays without having to explicitly check each time?

I want to avoid using the `|` operator in TypeScript which requires checking if a variable is an array or not, as I always know if it's an object or an array. Instead of using `as SomeType` or `as SomeType[]`, I'd like to be able to use `?.` everywhere.

One solution I've tried is defining a mixture of object and array:

interface _Array<T> extends Array<T | undefined> {}
type ArrayORObject<T> = Partial<T> & Partial<_Array<T>>;

This almost works, but now I'm running into an issue where I get "Index signature for type 'number' is missing in type SomeObject." It seems that objects need an array index signature ([index: number]), but I can't figure out how to make it optional.

Edit: Upgrading to the beta version of TS isn't feasible right now, so adding calls to functions like makeOrder() isn't much better than just manually checking for arrays.

For a better example, you can check out this TS Playground

Answer №1

Two object literals, order1 and order2, are at your disposal. Order1 contains a single burger while order2 includes an array of burgers. Unfortunately, this distinction is lost when you assign them an explicit type with a union.

Removing the explicit type provides a precise constant type, but there's no guarantee it aligns with the order interface.

Introducing TS 4.9, a satisfies keyword tackles this issue:

const order1 = {
    main: { meat: 'beef' }
} satisfies order;

Playground link to TS 4.9 solution

You need not rely on TS 4.9 as functions offer robust type inference:

function makeOrder<T extends order>(o: T): T {
  return o;
}

const order1 = makeOrder({
    main: { meat: 'beef' }
});

Playground link to TS 4.8 solution

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

The Angular Firebase query is being run repeatedly

I'm currently facing an issue in my project where Firebase queries are being executed multiple times. This problem wasn't present during development and no changes have been made to the Firebase dependencies. Below is a snippet of code that used ...

What is the best way to choose an ID that changes based on the index position?

Let me clarify my point first. Within a dropdown menu, there are 5 buttons - 2 with fixed IDs and 3 that can be altered through a separate micro service (such as when changing break types). The IDs for these 3 buttons are dynamically generated based on th ...

Guide to incorporating code coverage in React/NextJs using Typescript (create-next-app) and cypress

I initiated a fresh project using create-next-app with the default settings. npx <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="365544535742531b58534e421b57464676070518021801">[email protected]</a> --- Would you l ...

The Azure function encounters an AuthorizationFailure error while attempting to retrieve a non-public file from Azure Blob Storage

Within my Azure function, I am attempting to retrieve a file from Blob Storage labeled myappbackendfiles. The initial code (utils/Azure/blobServiceClient.ts) that initializes the BlobServiceClient: import { BlobServiceClient } from "@azure/storage-bl ...

Having trouble showing JSON data with Ionic 2 and Xcode?

Extracting JSON data from a JSON file in my project and viewing it using "ionic serve" on my Mac has been successful. However, I am facing an issue after building for IOS in XCode. I import the generated project into XCode as usual, but the JSON data is no ...

Error in Firebase Functions: Promises must be properly managed

Currently, I am in the process of creating a Firebase function using TypeScript to deliver push notifications to multiple users. However, whenever I execute the command firebase deploy --only functions, TSLint flags an error stating "Promises must be han ...

Get a list of objects from a JSON array of objects using HTTP requests in Angular 5 with Typescript

I am trying to extract an array of objects from another JSON array, which is received through an HTTP request in Angular 5. My goal is to display the values in the console. I have successfully made the HTTP request and subscribed to the service. When usin ...

Trigger an event in Angular using TypeScript when a key is pressed

Is it possible to activate a function when the user presses the / key in Angular directly from the keydown event? <div (keydown.\)="alerting()"> </div> <div (keydown.+)="alerting()"> </div> Both of these ...

Customizable TypeScript interface with built-in default key value types that can be easily extended

One common pattern that arises frequently in my projects involves fetching values and updating the UI based on the 'requestStatus' and other associated values. type RequestStatus = | 'pending' | 'requesting' | 'succ ...

Change (EU Time) date format of dd/mm/yyyy hh:mm:ss to a timestamp

Is there a way to convert time into a timestamp? I attempted to use .getTime(), but it seems to be switching the day and month. const date = new Date('01-02-2003 01:02:03'); console.log(date.getTime()); It appears to be converting to the US Tim ...

Tips for Implementing Guard in Angular Applications Without Using Components

My objective is to trigger a method and redirect to component A or B when the link 'auth/login/:tokenKey' is accessed. However, for this specific link, no component is needed, just a method in the typescript file. How can I achieve this? GetTok ...

I am interested in creating a class that will produce functions as its instances

Looking to create a TypeScript class with instances that act as functions? More specifically, each function in the class should return an HTMLelement. Here's an example of what I'm aiming for: function generateDiv() { const div = document.crea ...

Lock the table header in place as the table content scrolls upward using Angular4

Is there a way to keep the table header fixed in place while the rest of the content scrolls up? Below is a snippet from my .html file: <table class="table sticky-header"> <thead> <tr class="row-hor- ...

What steps are involved in ensuring that this NodeJS package is compatible with browsers?

My latest pet project was built using nodejs, a technology I chose due to my lack of previous experience with it and my curiosity. Now, I'm looking to modify this package so it can run in a browser and eventually be published on Bower. The npm packag ...

Angular 11 error: Datatable type is not defined

We have a services.ts file that requires 2 arguments. UPDATE: It appears that I was looking at the error incorrectly. This method is causing the console error: private checkLink(row, options) { if (options.type === 'link' || options.type ...

Is it possible to extract TypeScript types from one interface in order to integrate them into another separate interface?

Having a TypeScript interface defined as follows: interface SampleShape { prop1?: string; prop2?: string; } Additionally, I have another separate interface in mind to utilize: interface Payload { model: { name?: string; prop1?: ...

Using Angular to transform a JSON GET response into a class with methods

Essentially, I am working with an Angular component that has a variable called DashboardConfiguration which is set to an Observable. This Observable is obtained from a resolver that utilizes a service to make a GET request for a JSON object. The issue lie ...

Include a control within a form based on the Observable response

I am looking to enhance my form by adding a control of array type, but I need to wait for the return of an Observable before mapping the values and integrating them into the form. The issue with the current code is that it inserts an empty array control e ...

"Develop a unique Angular 12 custom pipe that retrieves data through a service and converts it into a string instead of

Hello Everyone, I've encountered a problem that I need help with. import { Pipe, PipeTransform } from '@angular/core'; import { PrintingTypesService } from 'src/app/settings/services/printing-types/printing-types.service'; import { ...

Is it possible to include multiple eventTypes in a single function call?

I have created a function in my service which looks like this: public refresh(area: string) { this.eventEmitter.emit({ area }); } The area parameter is used to update all child components when triggered by a click event in the parent. // Child Comp ...