505

I have an array of the form: [ 1, "message" ].

How would I define this in TypeScript?

1
  • Similar question to this one, with no answer, but this time using class inheritance with unknown number of items and all extending the same class: stackoverflow.com/questions/50322488/… Commented May 14, 2018 at 2:44

10 Answers 10

855

Defining array with multiple types in TypeScript

Use a union type (string|number)[] demo:

const foo: (string|number)[] = [ 1, "message" ];

I have an array of the form: [ 1, "message" ].

If you are sure that there are always only two elements [number, string] then you can declare it as a tuple:

const foo: [number, string] = [ 1, "message" ];

And you can even provide meaningful names for the tuple members e.g. id and text:

const foo: [id: number, text: string] = [ 1, "message" ];
Sign up to request clarification or add additional context in comments.

5 Comments

Just a note that this will require TS v1.4+
... and it won't work with complex types with different properties, when you want to access a property available on only one of the types.
@Nadine And in that case, what could one do?
Each time when you are clear about which type it is, you can do a type assertion. Then it will work to access the properties.
Good point @seawave_23, I suggest you edit the accepted answer with this information if possible
114

If you're treating it as a tuple (see section 3.3.3 of the language spec), then:

var t:[number, string] = [1, "message"]

or

interface NumberStringTuple extends Array<string|number>{0:number; 1:string}
var t:NumberStringTuple = [1, "message"];

3 Comments

TIP: I would prefer type NumberStringTuple = [number, string]
Thanks! I was totally looking for this: const W3COLORS: [[string, string, number, number]] = [ ["aliceblue", "#f0f8ff", 240, 248, 255], ... ];
Note - both types MUST be in the array (doesn't work for an empty array as well). Accepted answer is more versatile and which I personally always use, but it depends on the needs.
61

My TS lint was complaining about other solutions, so the solution that was working for me was:

item: Array<Type1 | Type2>

if there's only one type, it's fine to use:

item: Type1[]

3 Comments

This is great, but say if we're looping over the array now, how do we figure out which type the current array is?
Sure, but what if I want an array type where the first element can only be a string, and the second element can only be a number?
45

TypeScript 3.9+ update (May 12, 2020)

Now, TypeScript also supports named tuples. This greatly increases the understandability and maintainability of the code. Check the official TS playground.


So, now instead of unnamed:

const a: [number, string] = [ 1, "message" ];

We can add names:

const b: [id: number, message: string] = [ 1, "message" ];

Note: you need to add all names at once, you can not omit some names, e.g:

type tIncorrect = [id: number, string]; // INCORRECT, 2nd element has no name, compile-time error.
type tCorrect = [id: number, msg: string]; // CORRECT, all have a names.

Tip: if you are not sure in the count of the last elements, you can write it like this:

type t = [msg: string, ...indexes: number];// means first element is a message and there are unknown number of indexes.

TypeScript 4.x+ Variadic Tuple Types

The last example has to be changed to this one for TS 4.x:

type t = [msg: string, ...indexes: number[]];// means first element is a message and there are unknown number of indexes.

The type number is changed to number[].

More info here: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html#variadic-tuple-types

2 Comments

What is it for? The names on tuple elements?
@Marecky it was added for ease of use, e.g. hint from TypeScript compiler: (property) 0: number (id) instead of unified (property) 0: number. So, there will be more details in the error message too, if any.
28

I've settled on the following format for typing arrays that can have items of multiple types.

Array<ItemType1 | ItemType2 | ItemType3>

This works well with testing and type guards. https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-guards-and-differentiating-types

This format doesn't work well with testing or type guards:

(ItemType1 | ItemType2 | ItemType3)[]

Comments

8

Im using this version:

exampleArr: Array<{ id: number, msg: string}> = [
   { id: 1, msg: 'message'},
   { id: 2, msg: 'message2'}
 ]

It is a little bit similar to the other suggestions but still easy and quite good to remember.

Comments

6

If you are interested in getting an array of either numbers or strings, you could define a type that will take an array of either

type Tuple = Array<number | string>
const example: Tuple = [1, "message"]
const example2: Tuple = ["message", 1]

If you expect an array of a specific order (i.e. number and a string)

type Tuple = [number, string]
const example: Tuple = [1, "message"]
const example2: Tuple = ["messsage", 1] // Type 'string' is not assignable to type 'number'.

Comments

6
const myarray:(TypeA | TypeB)[];

or even better to avoid changes in multiple place in case you need to add another type, create type

type MyMixedType = TypeA | TypeB;
const myarray: MyMixedType[];

Comments

1
[ 1, "message" ] as const ;

if you do "as const" , type will be

type const = readonly [1, "message"]

It is good because of the exact type inference that computer can possible.

Comments

0

If dealing with an array with multiple value types in an object this worked for me.

 { [key: string]: number | string }[]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.