Steps to declare a constant array in TypeScript

Here's My Code:

const WEEKDAYS_SHORT: string[] = ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam']

The TypeScript (3.0) compiler throws an error message:

TS2322: Type 'string[]' is not assignable to type '[string, string, string, string, string, string, string]'. Property '0' is missing in type 'string[]'.

https://i.sstatic.net/rhZWw.png

If I change the string[] to ReadonlyArray<string>, then the error message changes to:

TS2322: Type 'ReadonlyArray' is not assignable to type '[string, string, string, string, string, string, string]'. Property '0' is missing in type 'ReadonlyArray'.

Here's my tsconfig.json:

{
  "compilerOptions": {
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": ["es6", "dom"],
    "module": "es6",
    "moduleResolution": "node",
    "sourceMap": true,
    "target": "es5",
    "jsx": "react",
    "strict": true
  },
  "exclude": [
    "**/*.spec.ts",
    "node_modules",
    "vendor",
    "public"
  ],
  "compileOnSave": false
}

How can I define a readonly array in TypeScript?

Answer №1

Emphasize your array declaration by adding as const;

const readonlyArray = [1, 2, 3] as const;

It's easy to access the element type of a readonly array:

type Element = typeof readonlyArray[number]` // 1 | 2 | 3

The as const assertion can be used for any declarations, even objects and deeply nested data structures. You can also assert an expression as const. For instance, if the value 1 is inferred as a number, but you want to specify the number literal type, simply assert it as 1 as const. This feature was introduced in TypeScript version 3.4. Further information can be found in the documentation.

Note that a readonly or const array is often referred to as a tuple (similar to Python - see reference). Tuples may contain elements of the same type or different types. In the example above, the Element type is not inferred as number but as a union of number literals. This is because tuple elements are immutable. It's beneficial to infer the most specific type possible. For instance, you can use the number literal type 1 in place of a number, but not vice versa.

A pair with two elements is commonly known as a tuple and can be represented as a product. Although the product of [number, string] is not a number, their combination allows multiplication. Consider a simpler example like [1 | 2 | 3, 'a' | 'b' | 'c'], which expands to:

  [1, 'a']
| [1, 'b']
| [1, 'c']
| [2, 'a']
| [2, 'b']
| [2, 'c']
| [3, 'a']
| [3, 'b']
| [3, 'c']

For further exploration:

Answer №2

Although the verified solution is accurate, there is a slight downside.

const readonlyArray = [1, 2, 3] as const;

let x = 4; // function parameter, etc.
// Argument of type 'number' is not assignable to parameter of type '1 | 2 | 3'.ts(2345)
// if (readonlyArray.includes(x)) {}

An alternative approach would be to utilize readonly:

const readonlyArray: readonly number[] = [1, 2, 3];

let x = 4;
if (readonlyArray.includes(x)) {} // OK

// Property 'push' does not exist on type 'readonly number[]'.ts(2339)
// readonlyArray.push(4);

Answer №3

Upon thorough investigation, it became apparent that the issue was not with the TypeScript compiler, but rather stemmed from my usage of a third-party component called DayPicker:

          <DayPicker
            onDayClick={this.handleDayClick}
            selectedDays={posts.day}
            months={MONTHS}
            weekdaysShort={WEEKDAYS_SHORT}
            firstDayOfWeek={1}/>

I discovered that the type of the prop weekdaysShort is not string[], but actually

[string, string, string, string, string, string, string]

weekdaysShort?: [string, string, string, string, string, string, string];

Because of this discrepancy, the TS compile threw an error stating that string[] does not match

[string, string, string, string, string, string, string]
.

To resolve this issue and eliminate the annoying error message, I simply changed the type from string[] to any. Alternatively, we could have also changed it to

[string, string, string, string, string, string, string]
(but it's too lengthy).

Answer №4

The issue was not replicated during testing on the TypeScript playground.

What if we utilize the inferred type, whether it be a string array string[] or a 7-string tuple

[string, string, string, string, string, string, string]
?

const WEEKDAYS_SHORT = ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'];
const sunday = 0;
const dayShortName = WEEKDAYS_SHORT[sunday]; // => 'Dim'

Or possibly an enum?

enum WEEKDAYS_SHORT { 'Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam' }
const sunday = 0;
const dayShortName = WEEKDAYS_SHORT[sunday]; // => 'Dim'

In my opinion, both of the aforementioned options are superior to specifying the type any in this scenario.

Answer №5

Identifying the issue you've raised, it arises from attempting to assign a string array (string[]) to a 7-string-tuple. While your use of any can provide a solution, it's generally not recommended due to its lack of specificity. Additionally, spelling out the tuple type manually is cumbersome given its length.

To address this, we can create a utility function that generates tuple types for us. This approach ensures reusability in scenarios requiring tuples:

function tupleArray<T extends any[]>(...v: T) {
    return v;
}
const WEEKDAYS_SHORT_INFFERED =  tupleArray('Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam')  // INFFERED AS [string, string, string, string, string, string, string]
const WEEKDAYS_SHORT: [string, string, string, string, string, string, string] = WEEKDAYS_SHORT_INFFERED

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

Utilize PHP's prepared statements to store an array in a MySQL database efficiently

I am working with an input array that I need to insert into a database. Instead of having each item in the array create a new row in the database, I want all the items to be added to the same row. Here is the code I have so far: <?php session_start(); ...

How can we determine the props' type specific to each component?

type ComponentCProps = { c: string; }; function ComponentC(props: ComponentCProps) { return <div>component C</div>; } type ComponentDProps = { d: string; }; function ComponentD(props: ComponentDProps) { return <div>component D& ...

Having trouble getting Jest to manually mock in Nestjs?

When setting up a mock service like this: // /catalogue/__mock__/catalogue.service.ts export const CatalogueService = jest.fn().mockImplementation(() => { return { filterRulesFor: jest.fn().mockImplementation((role: Roles): Rule[] => rules.filt ...

There appears to be an issue with the compilation of the TypeScript "import { myVar }" syntax in a Node/CommonJS/ES5 application

In my Node application, I have a configuration file that exports some settings as an object like this: // config.js export var config = { serverPort: 8080 } Within another module, I import these settings and try to access the serverPort property: // ...

Is there a way to specifically target the MUI paper component within the select style without relying on the SX props?

I have been experimenting with styling the Select MUI component using the styled function. I am looking to create a reusable style and move away from using sx. Despite trying various methods, I am struggling to identify the correct class in order to direct ...

"Using Angular and TypeScript to dynamically show or hide tabs based on the selected language on a website

When switching the language on the website, I want to display or hide a specific tab. If the language is set to German, then show the tab; if any other language is selected, hide it. Here's my code: ngOnInit(): void { this.translate.onLangChange.s ...

Discovering indices within an array that fall within a specified range of values in bulk

Seeking ideas on how to expedite the process of identifying indices that fall within a specific range. Imagine having a 1d array of sorted values (~50k) and a sizable list (>100k) containing pairs of min/max values. The aim is to determine which indices ...

What is the best way to initialize a dynamic array in C++?

Is there a way to achieve the dynamic equivalent of initializing this static array? char c[2] = {}; // Sets all members to '\0'; In simpler terms, how can I create a dynamic array with all values set to the null character? char* c = new ...

warning TS2322: Cannot assign type 'PropUser | null' to type 'PropUser'

Issue: Error: src/app/user/containers/shell-user-profile/shell-user-profile.component.html:1:20 - error TS2322: Type 'PropUser | null' is not assignable to type 'PropUser'. Type 'null' is not assignable to type 'Pro ...

Error in TypeScript - Anticipated 1-2 arguments, received either none or multiple. Code Issue TS2556

While working in JavaScript, I had no issues with this code snippet. However, when I attempted to implement it in a TypeScript Project, an error surfaced. The problem seems to revolve around the fetch(...args) function call. const fetcher = (...args) =&g ...

"Exploring the versatility of PHP arrays with a mixture of images

I'm attempting to showcase an image in a PHP Array. Here's what I have: View: <?php include "controllers/Autos.php"; ?> <!DOCTYPE html> <html> <head> <title>Autos</title> </head> <bo ...

Obtain abbreviated names for the days of the week starting from Monday to Sunday using JavaScript

Is there a way to retrieve the abbreviated names of each day of the week in JavaScript, starting from Monday through Sunday? ...

Is it possible to define data types for the global context in cucumber?

Embarking on a fresh cucumber-selenium project in Typescript, I am eager to keep the Driver in the world context. However, following the method suggested here, I encounter an issue where the Driver type remains inaccessible to step definitions. This means ...

Generating nested arrays within an array continuously with numpy

I have two lists: a=[1,2,3] and b=[4,5,6] I decided to combine these lists into an array of arrays by using: c=np.array([[a],[b]]) Now I am wondering how to implement this in a loop. Can I create an empty array and then add arrays to it? If I call ...

How to Link an Observable Array to Another in Angular 2

In my Angular 2 project, I am trying to chain multiple HTTP calls together. Initially, I retrieve an array of environments with one call. For each environment, I want to make another call and create objects like firstObject[{name:"name",secondObject[stuff ...

Ran into a situation where Nextjs13 had two children sharing the same key

Currently, I am in the process of creating a booking form using shadcn/ui within nextjs13. As part of this, I am mapping over different hairstyles listed in my postgres database to generate selectable options for users. However, during this process, I enco ...

Embedding HTML Tags within an array element

The task at hand involves adding an HTML element from Array Value to the Document Object Model template: { 0: { h1: '<h1>Hi</h1>' }, 1: { h2: '<h2>Hi</h2>' }, 2: { h3: &a ...

CORS policy is causing the POST request to be blocked, but the GET and DELETE requests

I've encountered a strange issue with my application. The architecture of my app is as follows: ts (Angular) -> Java (Spring). I was making some GET requests from Angular to Java, as well as DELETE requests without any problems. However, when I tri ...

Issues arising when selecting a property within a C# method

Seeking assistance in c# as a newcomer to the language. I am currently working on adding two cars to an array. My goal is to determine the longest car length in the `Greateslength()` function. However, I am facing difficulty in selecting Carlength or an ...

What is the proper way to utilize e.key and e.target.value in TypeScript when coding with React?

I'm struggling to get e.key and e.target.value working with the following code: const handleInputKeyPress = (e: React.KeyboardEvent<HTMLInputElement> ) => { if(e.key ==='Enter') { dfTextQuery(e.target.value) } }; Why is & ...