Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define a const array in typescript

My Code:

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

the error message comes from TypeScript (3.0) compiler:

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

enter image description here

if I change the string[] to ReadonlyArray<string>, then the error message becomes:

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

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?

like image 506
Spark.Bao Avatar asked Aug 16 '18 06:08

Spark.Bao


People also ask

Can an array be const?

Arrays are Not Constants The keyword const is a little misleading. It does NOT define a constant array. It defines a constant reference to an array. Because of this, we can still change the elements of a constant array.

How do you create an array constant?

You can also use array constants, values you just enter in the formula bar inside braces: {}. Then you can name your constant so it's easier to use again. You can use constants in your array formulas or by themselves. The constant is inside the braces ({)}, and yes, you really do type those braces manually.

Can you add to a const array Javascript?

The property of a const object can be change but it cannot be change to reference to the new object. The values inside the const array can be change, it can add new items to const arrays but it cannot reference to a new array.


2 Answers

Assert your array declaration as const;

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

Additionally, accessing the element type of a readonly array is trivial:

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

as const assertions work on any declarations, including objects and deeply nested data structures. You can even assert an expression as const. For instance, if the value 1 is inferred as a number, but you want to supply the number literal type, simply assert it 1 as const. The feature was introduced in TypeScript 3.4. You can also reference the docs.

Bear in that a readonly or const array is often called a tuple (as is the case in Python - reference). Tuples can have elements of the same type or elements of entirely different types. Notice, that in the above example the Element type was not inferred as number but as a union of number literals. This is possible because the elements of the tuple are never going to change. It is practical to infer the narrowest possible type. You can, for example, use the number literal type 1 anywhere where a number is required, but you cannot use the number type where the number literal type 1 is required.

A tuple of two elements is often called a pair and may be represented as a product. Although the product of [number, string] is not a number, you can still multiply them together. Because both string and number are infinitely large themselves, so is their product type. Consider simpler example of [1 | 2 | 3, 'a' | 'b' | 'c'], which is equal to:

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

Further reading:

  • readonly and const
  • Product Types
like image 72
Mateja Petrovic Avatar answered Sep 17 '22 14:09

Mateja Petrovic


After debugging, I found it is not TypeScript compiler problem, it is because I used a third-party component call DayPicker:

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

the type of the prop weekdaysShort is not string[], but [string, string, string, string, string, string, string]

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

so TS compile says string[] doesn't match [string, string, string, string, string, string, string].

finally, I just changed the type from string[] to any to avoid this anoy error message, of course, we can change to [string, string, string, string, string, string, string] as well (too long).

like image 40
Spark.Bao Avatar answered Sep 20 '22 14:09

Spark.Bao