Menu

TypeScript Array: Types, Arrays of Objects, map and filter

How to type arrays in TypeScript: T[] vs Array<T>, arrays of objects, arrays that hold several types, readonly arrays, and what map, filter, reduce and find return. Plus the includes pitfall with literal arrays.

This page includes runnable editors - edit, run, and see output instantly.

A TypeScript array type is the element type followed by []: string[] is an array of strings, number[] an array of numbers. The generic spelling Array<string> is the same type. Once an array is typed, every element you add and every element you read has that type.

The @ts-expect-error line is a compile error (TS2345). Here it is marked as expected so the block still runs, and since types are erased, the 42 really is pushed at runtime: the output shows it.

string[] vs Array<string>

Written asSame asNotes
string[]Array<string>The common spelling.
(string | number)[]Array<string | number>Parentheses are required: string | number[] means "a string, or an array of numbers".
readonly string[]ReadonlyArray<string>No push, pop, sort or index assignment.
User[]Array<User>Arrays of objects use the object's type.
string[][]Array<Array<string>>A 2D array (grid).

Pick one style for a codebase. typescript-eslint's array-type rule defaults to T[].

Arrays of Objects

Describe the element with a type alias or interface, then use Type[]. Everything read out of the array is checked against that shape.

An object literal pushed into users must match User exactly: a missing admin or a misspelled property is a compile error.

Typed map, filter, reduce and find

The array methods are generic, so their results carry types. What each method does at runtime is covered on the JavaScript array methods page; the types are what TypeScript adds:

MethodResult type on T[]
map(fn)U[], where U is what fn returns
filter(fn)T[] (or a narrower type, see below)
find(fn)T | undefined
findIndex(fn), indexOf(x)number (-1 if absent)
some(fn), every(fn), includes(x)boolean
reduce(fn, init)the type of init (or the type argument, reduce<R>(...))
at(i)T | undefined
join(sep)string

The last example works because TypeScript (since 5.5) infers that (n) => n !== undefined is a type predicate, so filter returns number[] rather than (number | undefined)[]. For checks it cannot infer, write the predicate yourself: filter((x): x is User => x !== null).

Arrays That Hold More Than One Type

A union element type allows a mix. A union of array types does not:

When positions have fixed types, like a [name, age] pair, use a tuple instead: [string, number] knows that index 0 is a string and index 1 is a number, where (string | number)[] does not.

Readonly Arrays

readonly T[] removes every method that mutates the array. Use it for parameters a function should not change, and for constants.

index.ts(3,12): error TS2339: Property 'push' does not exist on type 'readonly number[]'.

Delete the push line and the block prints 4. A mutable number[] can always be passed where readonly number[] is expected, so readonly parameters cost callers nothing. The check is compile-time only: at runtime it is an ordinary array. To sort a readonly array, sort a copy: [...values].sort().

The includes Pitfall with Literal Arrays

as const turns an array into a readonly tuple of literal types. That is useful for a list of allowed values, but its includes then only accepts those literals:

Wrapping the check in a type guard (value is Color) means the widening happens once, and callers get a narrowed value back.

Indexing and Empty Arrays

Reading arr[i] gives type T, even when i is out of range and the runtime value is undefined. at(i) is typed T | undefined, and the compiler option noUncheckedIndexedAccess makes plain indexing return T | undefined too.

queue[0].toUpperCase() would compile and then throw a TypeError at runtime. Prefer at(), a length check, or noUncheckedIndexedAccess when an index may be missing.

Frequently Asked Questions

How do you declare an array type in TypeScript?

Write the element type followed by []: let names: string[] = ["a", "b"]. The generic form Array<string> means exactly the same thing. For an array of objects, use an object type or interface as the element type: User[].

What is the difference between string[] and Array<string>?

None: they are two spellings of the same type. string[] is more common. The generic form reads better for complex element types, and for readonly arrays readonly string[] and ReadonlyArray<string> are likewise the same.

Why does find return undefined in TypeScript?

array.find() returns T | undefined because nothing may match. Under strict you must handle the undefined case, with an if check, optional chaining (found?.name) or a default (found ?? fallback), before using the result.

How do I type an array with multiple types in TypeScript?

Use a union element type in parentheses: (string | number)[] is an array where each element is a string or a number. That is different from string[] | number[], which is either an array of only strings or an array of only numbers. For a fixed order of types, such as [string, number], use a tuple.

Why does includes give an error on an as const array?

A readonly array of literals, such as ["red", "green"] as const, has includes(searchElement: "red" | "green"), so passing a plain string is error TS2345. Widen the array for the check, (COLORS as readonly string[]).includes(input), ideally inside a type guard that narrows input to the literal union.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED