Suggest an editImprove this articleRefine the answer for “Mixed types in an array”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)An array with elements of **different types** is declared through a type union `|`, for example `(string | number)[]`, or through generic syntax `Array<string | number>`. **Key point:** if the number and order of the types are known in advance, a tuple is a better fit than an array of unioned types.Shown above the full answer for quick recall.Answer (EN)Image## 1. Basic approach: a union of types via `|` ```javascript const mixed: (string | number)[] = [1, "two", 3, "four"]; ``` > Here each element can be **either** `string` **or** `number`. > TypeScript checks this and offers hints in the IDE. --- ### Alternative via generics ```javascript const mixed: Array<string | number> = [1, "two", 3]; ``` > The same thing, but in generic syntax. --- ## 2. An array with three or more types ```javascript const data: (string | number | boolean)[] = [42, "text", true]; ``` > You can combine any number of types. --- ## 3. An array of objects of different shapes (for example, messages) ```javascript type TextMessage = { type: "text"; text: string }; type ImageMessage = { type: "image"; url: string }; const messages: (TextMessage | ImageMessage)[] = [ { type: "text", text: "Hello!" }, { type: "image", url: "photo.jpg" }, ]; ``` > TypeScript will "narrow" the type on its own during checks: ```javascript for (const msg of messages) { if (msg.type === "text") console.log(msg.text); else console.log(msg.url); } ``` --- ## 4. When elements have a *fixed order* -> a **tuple** is better If the number and order of the types are known in advance: ```javascript const tuple: [string, number, boolean] = ["Tim", 25, true]; ``` > This is not an "array of different types", it is a **tuple**. > Each index has its own type: > > - `tuple[0]` is string > - `tuple[1]` is number > - `tuple[2]` is boolean --- ## 5. An example mixing objects and primitives ```javascript const values: (number | string | { id: number })[] = [ 1, "two", { id: 3 }, ]; ``` > TypeScript will only allow these types. --- ## 6. An example using `typeof` to infer a type ```javascript const mixed = [1, "text", true] as const; type MixedElement = typeof mixed[number]; // MixedElement -> 1 | "text" | true ``` > Using `as const` you can get a **union of the array's specific values**. --- ## 7. An array of elements from different classes (through a shared base type) ```javascript class Dog { bark() {} } class Cat { meow() {} } const pets: (Dog | Cat)[] = [new Dog(), new Cat()]; ``` > TypeScript understands which method is available on which instance: ```javascript pets.forEach(pet => { if (pet instanceof Dog) pet.bark(); else pet.meow(); }); ``` --- ## 8. What happens if you do not specify the type explicitly ```javascript const arr = [1, "hi"]; // The type is inferred automatically as (string | number)[] ``` > TypeScript infers the union types of the elements on its own, > if you mixed them at initialization. --- ## Summary | Task | Syntax | Example | |---|---|---| | Primitives of different types | `(string \| number)[]` | `[1, "a", 2]` | | Several types | `(string \| number \| boolean)[]` | `[1, "x", true]` | | Array of objects of different shapes | `(A \| B)[]` | `[{type:"a"}, {type:"b"}]` | | Fixed order of types | `[string, number, boolean]` | `["a", 1, true]` | | Via generics | `Array<string \| number>` | `[1, "b"]` | | Automatic inference | no explicit type | `[1, "x"] // -> (string |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.