Entering a series of predetermined value types into an array

I am currently trying to determine the best way to define a type for a specific value in TypeScript. The value in question looks like this:

[{"source": "bar"}, 1483228800, 1484265600]

Initially, I came up with the following approach:

interface FieldSource {
  source: string;
}

interface SearchWhereClause {
  between: [FieldSource, number, number]
}

While this code compiles without errors, I am uncertain if it is the most appropriate method.

I have also considered using:

(FieldSource | number | number)[]

However, in my specific case, I explicitly want the array to consist of my object and two number values.

Could someone please offer some guidance on the best approach to defining this type?

Thank you

Answer №1

In my particular scenario, I am aiming for the array to consist of my object and two numeric values.

If this is truly your requirement, then your current method is absolutely correct, with the condition that the types in the array must follow that specific order.

(FieldSource | number )[] is distinct from [FieldSource, number, number]), take this into account:

interface MyInterface {
  prop: number
}

type MyTuple = [MyInterface, number, number]
type MyArr = (MyInterface | number)[]

const myTup: MyTuple = [{ prop: 2 }, 2, 2] // <-- can only have two numbers
const myArr: MyArr = [{ prop: 2 }, 2, 2, 2, 2] // <-- can have any amount of numbers
const myArrAsTup: MyTuple = [{ prop: 2 }, 2, 2, 2, 2] // <-- not assignable to type

(FieldSource | number )[], which is the same as

(FieldSource | number | number)[]
, specifies that the array can include any of those values in any order and quantity.

[FieldSource, number, number] is referred to as a Tuple type, it enforces the types allowed in an array, their positions, and the array's length.

type MyTuple = [MyInterface, number, number]

const tupleOne: MyTuple = [2, 2, {prop: 2} ] // <-- not assignable
const tupleTwo: MyTuple = [2, {prop: 2}, 2] // <-- not assignable

This also makes it easier for typescript to determine the types of items retrieved from the array using indexing or destructuring:

const [interfaceInstance] = myTup // <-- type is MyInterface
const aNumber = myTup[1] // <-- type is number

If you are unable to ensure the type order (or prefer not to), you can utilize a union of multiple tuples:

// less verbose, weaker inference
type TupleMember = (MyInterface | number)
type MyTuple = [TupleMember, TupleMember, TupleMember]

// more verbose, still able to infer types of tuple members
// as long as those tuples are defined somewhere in your codebase
// and not generated from an external source, like an API call
type MyTuple = 
  [MyInterface, number, number] |
  [number, MyInterface, number] |
  [number, number, MyInterface]

Answer №2

Just like @hereticMonkey pointed out in the question's comment section, this is quite similar to another discussion on defining arrays with multiple types in TypeScript. You can check it out here.

For your specific query, if you're in need of a defined set, then a Tuple would be the right choice.

(FieldSource | number | number)[]
is essentially the equivalent of
Array<FieldSource | number | number>
, which means it can accommodate any of those types in any sequence within an array of variable length.

On a side note, it's recommended to use

type FieldSource = { source: string }
instead of interface unless you intend to use it within a class. This offers more power, clarity, and flexibility compared to an interface.

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

Evaluating function declaration - comparing interface to type alias

Here is a function that I need to create a validator for: function (n: number) { return {s: n}; } I have come across two options for creating the validator: Option 1: Interface interface ValidatorFnInterface { (n: number): { [key: strin ...

Is there a way to deactivate a tab when it's active and reactivate it upon clicking another tab in Angular?

<a class="nav-link" routerLink="/books" routerLinkActive="active (click)="bookTabIsClicked()" > Books </a> I am currently teaching myself Angular. I need help with disabling this tab when it is active ...

Is there a way for me to connect to my Firebase Realtime Database using my Firebase Cloud Function?

My current challenge involves retrieving the list of users in my database when a specific field is updated. I aim to modify the scores of players based on the structure outlined below: The Realtime Database Schema: { "users": { &quo ...

Issues arise when Typescript fails to convert an image URL into a base64 encoded string

My current challenge involves converting an image to base 64 format using its URL. This is the method I am currently using: convertToBase64(img) { var canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.he ...

Difficulty with the value binding issue on input text produced by *NgFor

When using *ngFor in Angular to loop over an array and generate input text elements bound to the values in the array, I'm encountering some issues. The value is not binding correctly when a user inputs something into the text field. I attempted to ru ...

Hovering over the Chart.js tooltip does not display the labels as expected

How can I show the numberValue value as a label on hover over the bar chart? Despite trying various methods, nothing seems to appear when hovering over the bars. Below is the code snippet: getBarChart() { this.http.get(API).subscribe({ next: (d ...

styles.css is generating an ERROR message, indicating that it is unable to read properties of null when trying to access the 'classList'

Hey there, I've been working on adding a background color change to my navbar when the scrollY exceeds 30px, and it's functioning properly. However, I'm encountering an error in the console which states that the new classList cannot be added ...

"Element UI, featuring a wide array of components, contributing to bloated bundle sizes

I was looking into the following link. After following the instructions, I realized I am using class based components. Therefore, I am importing as shown below: import {Checkbox} from 'element-ui'; @Component({ components: { Checkbox } }) e ...

Component in Angular with an empty variable in TypeScript

I'm encountering an issue on my web page where I have a loop calling a component multiple times. I successfully pass data to the component, but the problem arises when I try to display the value of an object in the component. In the component's H ...

The 'resp' parameter is assumed to have an unspecified type, shown as 'any'. This is an error in Angular

} ErrorHandler(response){ console.debug(response.json()); } DataHandler(response){ this.ClientModels = response.json(); } I have developed two functions to handle error and success responses, but an error message is showing up saying "para ...

Dropdown Pattern with React CTA Modal

While using MaterialUI's ButtonGroup for a dropdown menu, I encountered an issue trying to set up a series of CTAs that are easily interchangeable within it. The goal is to have all components reusable and the choices in the dropdown dynamic. const C ...

tslint: no use of namespace and module is permitted

I have recently acquired a legacy .ts file that I would like to update. Two warnings appear: 'namespace' and 'module' are disallowed and The internal 'module' syntax is deprecated, use the 'namespace' keyword ins ...

Having trouble resolving the typescript package while integrating with another module

Attempting to develop a basic npm package with TypeScript and bundle it using webpack. When trying to use the package in another module, such as a react application named 'module A.' Within module A, the 'myLibrary' package is installe ...

The border of the Material UI Toggle Button is not appearing

There seems to be an issue with the left border not appearing in the toggle bar below that I created using MuiToggleButton. Any idea what could be causing this? Thank you in advance. view image here view image here Just a note: it works correctly in the ...

Transform the response from HttpClient into an array containing objects

In my Angular 7 project, I initially had the following code for the Envelope class: export class Envelope<T> { result: T[]; constructor(result: T[]) { this.result = result; } } Then, I mapped Observable<Envelope<Todo>> return ...

Tailor TypeScript to support various JavaScript versions

One of the advantages of TypeScript is the ability to target different versions of Javascript globally - allowing for seamless switching between transpiling ES3, ES5, or ES6. For browsers like IE that require ES3 support, it serves as the lowest common de ...

Using the parameter of type 'never' is necessary as per the TypeScript error message, which states that the argument of type 'string' cannot be assigned to it. This error persists even when

https://i.sstatic.net/tkX07.png const index = selectedActivities.value.indexOf(activity_id); I encountered a TypeScript error saying 'Argument of type 'string' is not assignable to parameter of type 'never'. How can I fix this iss ...

Attention Needed - Certain vulnerabilities necessitate manual review for resolution

npm audit === Security Report from npm audit === # You have 1 vulnerability that can be resolved by running `npm update terser-webpack-plugin --depth 3` Severity Issue ...

Mastering the Art of Utilizing Generic Typing to Access Objects

I am trying to find a way to access an object by class using generic typing. The issue I am encountering is that I am getting an error when trying to check if the locators contain an input field. type '{ form1: { item2: { checkbox: string; input: st ...

Tips for specifying a custom type as the return value of a function and denote it as a promise

I encountered this code snippet: import * as Promise from 'bluebird'; import {Response} from '../commonInterfaces/httpService'; getCall(url: string, accessToken: string, extraHeaders: object): Promise<Response> { let headers ...