Question

Array<Type> vs Type[] in TypeScript Explained

Question

In TypeScript, an array type for a property or variable can be written in two common ways:

let prop1: Array<string>;
let prop2: string[];

You can also use custom types:

let users1: Array<MyType>;
let users2: MyType[];

What is the difference between Array<Type> and Type[] in TypeScript? Are they equivalent, or do they behave differently? I may also be confusing the angle bracket syntax (<>) with type casting or another TypeScript feature.

Short Answer

By the end of this page, you will understand that Array<Type> and Type[] usually represent the same array type in TypeScript. You will learn how the two syntaxes work, when one may be easier to read than the other, how they relate to generics, and which style developers often choose in real projects.

Concept

In TypeScript, both Array<Type> and Type[] describe an array whose elements all have the same type.

For example, these mean the same thing:

let names: string[];
let otherNames: Array<string>;

Both variables are arrays of strings.

Why there are two syntaxes

TypeScript supports:

  • Bracket array syntax: Type[]
  • Generic array syntax: Array<Type>

The Array<Type> form uses a generic type. Array is a built-in generic type, and the type inside angle brackets tells TypeScript what kind of values the array contains.

So this:

Array<string>

means:

  • use the generic Array
  • fill in string as the element type

The shorter form:

string[]

is just alternative syntax for the same idea.

Why this matters

Understanding this helps you:

  • read different TypeScript codebases
  • understand generic types better
  • write clearer type annotations
  • avoid confusion between array syntax and angle-bracket type syntax

About the angle brackets

In Array<string>, the <string> part is not a cast. It is a generic type argument.

It tells TypeScript:

  • this is an Array
  • each item inside it is a string

That is different from older angle-bracket type assertions like:

let value = <string>someUnknownValue;

Those assertions exist in TypeScript, but they are a different feature. In modern TypeScript, developers often prefer as for type assertions:

let value = someUnknownValue as string;

So in your question, Array<string> is about declaring an array type, not casting.

Mental Model

Think of an array as a box that holds many items of the same kind.

  • string[] means: a box full of strings
  • Array<string> means: an array box configured to hold strings

These are two labels for the same kind of box.

Another way to think about it:

  • Type[] is the shorthand
  • Array<Type> is the generic form

Just like two routes leading to the same destination, both describe the same resulting type.

Take Quiz

Syntax and Examples

Basic syntax

let a: string[] = ["Alice", "Bob"];
let b: Array<string> = ["Alice", "Bob"];

Both variables are arrays of strings.

With custom types

type User = {
  id: number;
  name: string;
};

let usersA: User[] = [
  { id: 1, name: "Sam" },
  { id: 2, name: "Lee" }
];

let usersB: Array<User> = [
  { id: 3, name: "Ana" },
  { id: 4, name: "Max" }
];

Again, both forms mean the same thing.

Arrays of arrays

This is where readability can matter.

let grid1: number[][];
let grid2: Array<Array<number>>;

These are equivalent, but some people find one easier to read than the other.

Union example

When using union types, parentheses matter with Type[]:

let values1: (string | number)[] = ["a", 1, "b", 2];
let values2: Array<string | number> = ["a", 1, "b", 2];

These are equivalent.

Without parentheses, this means something different:

let onlyStringsOrNumbersArray: string | number[];

That means:

  • either a single string
  • or an array of number

It does not mean an array containing both strings and numbers.

Function example

function printNames(names: string[]): void {
  names.forEach((name) => console.log(name));
}

function printNamesGeneric(names: Array<string>): void {
  names.forEach((name) => console.log(name));
}

Both function parameters have the same type.

Step by Step Execution

Consider this code:

let scores: number[] = [10, 20, 30];

scores.push(40);

let firstScore: number = scores[0];

console.log(firstScore);

Step by step

  1. let scores: number[] = [10, 20, 30];

    • A variable named scores is created.
    • Its type is number[], meaning an array of numbers.
    • The array starts with three values: 10, 20, and 30.
  2. scores.push(40);

    • A new number is added to the array.
    • This is allowed because 40 is a number.
    • The array becomes [10, 20, 30, 40].
  3. let firstScore: number = scores[0];

    • The first element is read from the array.
    • scores[0] is 10.
    • It is stored in firstScore, which expects a number.
  4. console.log(firstScore);

    • The value 10 is printed.

Now compare the same logic with Array<number>:

let scores: Array<number> = [10, 20, 30];

Everything else behaves the same. Only the type syntax is different.

Real World Use Cases

Developers use typed arrays constantly in TypeScript projects.

Common examples

  • API responses
    • User[] for a list of users returned from a server
  • Form validation
    • string[] for validation error messages
  • UI rendering
    • Product[] for rendering product cards in a list
  • Data processing
    • number[] for scores, prices, or measurements
  • Configuration
    • Array<string> for supported locales or feature flags

Example: API data

type Post = {
  id: number;
  title: string;
};

function renderPosts(posts: Post[]): void {
  posts.forEach((post) => {
    console.log(post.title);
  });
}

Example: error collection

function validatePassword(password: string): string[] {
  const errors: string[] = [];

  if (password.length < 8) {
    errors.push("Password must be at least 8 characters.");
  }

  return errors;
}
Take Quiz

Real Codebase Usage

In real TypeScript codebases, both forms appear, but teams usually pick one style and use it consistently.

Common team preferences

  • Many developers prefer Type[] for simple arrays because it is short and easy to scan.
  • Some prefer Array<Type> because it matches other generic types like Promise<Type> or Map<Key, Value>.

Patterns in real projects

Function parameters

function saveUsers(users: User[]): void {
  // ...
}

Return types

function getIds(): Array<number> {
  return [1, 2, 3];
}

Readonly arrays

Developers often use readonly Type[] or ReadonlyArray<Type> when an array should not be changed.

function printTags(tags: readonly string[]): void {
  tags.forEach((tag) => console.log(tag));
}
function printTags(tags: ReadonlyArray<string>): void {
  tags.forEach((tag) => console.log(tag));
}

Validation and transformation

Typed arrays are often combined with:

  • map() to transform items
  • filter() to remove items
  • find() to locate one item
  • guard clauses to validate input early
function getActiveNames(users: User[]): string[] {
  return users
    .filter((user) => user.active)
    .map((user) => user.name);
}

Practical advice

Use one style consistently in a project. Consistency usually matters more than which of the two forms you choose.

Common Mistakes

1. Thinking Array<Type> and Type[] are different types

They are usually the same.

let a: string[] = ["x", "y"];
let b: Array<string> = ["x", "y"];

Both are arrays of strings.

2. Confusing generic syntax with type assertions

This is a generic type:

let names: Array<string> = ["A", "B"];

This is a type assertion:

let value = someData as string;

Do not mix those ideas together.

3. Forgetting parentheses with unions

Broken meaning:

let values: string | number[];

This means:

  • a string
  • or a number[]

If you want an array whose items can be either type, write:

let values: (string | number)[];

Or:

let values: Array<string | number>;

4. Mixing up array of union vs union of arrays

These are not the same:

let a: (string | number)[];
let b: string[] | number[];
  • a can contain both strings and numbers together
  • b must be either all strings or all numbers

5. Inconsistent style in the same file

This is valid, but can hurt readability:

let ids: number[] = [1, 2, 3];
let names: Array<string> = ["A", "B"];

Prefer a consistent convention unless there is a clear readability reason.

Comparisons

Type[] vs Array<Type>

SyntaxExampleMeaningNotes
Type[]string[]Array of stringsShort and common
Array<Type>Array<string>Array of stringsGeneric style

Equivalent examples

ThisSame as
number[]Array<number>
User[]Array<User>
`(stringnumber)[]`
number[][]Array<Array<number>>

Related comparison: mutable vs readonly arrays

TypeExampleCan modify?
Mutable arraystring[]Yes
Mutable arrayArray<string>Yes
Readonly arrayreadonly string[]No
Readonly arrayReadonlyArray<string>No

When one may be clearer

  • Use Type[] when the element type is simple: string[], User[]
  • Use Array<Type> when you want consistency with generics such as Promise<User>
  • For more complex nested or union types, choose whichever is easier to read
Take Quiz

Cheat Sheet

// Equivalent array types
let a: string[];
let b: Array<string>;

// Custom types
type User = { id: number; name: string };
let users1: User[];
let users2: Array<User>;

// Union items
let mixed1: (string | number)[];
let mixed2: Array<string | number>;

// Nested arrays
let matrix1: number[][];
let matrix2: Array<Array<number>>;

// Readonly arrays
let tags1: readonly string[] = ["ts", "js"];
let tags2: ReadonlyArray<string> = ["ts", "js"];

Rules to remember

  • Type[] and Array<Type> are usually equivalent.
  • Array<Type> uses generic syntax.
  • <> in Array<string> is not casting.
  • Use parentheses with unions in Type[] syntax: (A | B)[]
  • Be consistent with style in a codebase.

Easy choices

  • Simple arrays: string[]
  • Generic-style consistency: Array<string>
  • Readonly arrays: readonly string[] or ReadonlyArray<string>

FAQ

Is Array<string> the same as string[] in TypeScript?

Yes. In normal TypeScript usage, they describe the same type: an array of strings.

Which is better: Array<Type> or Type[]?

Neither is more correct. Most teams choose one based on readability and consistency.

Does Array<string> use casting?

No. The <string> part is a generic type argument, not a cast.

When should I use parentheses with Type[]?

Use parentheses when the element type is a union, such as (string | number)[].

Is string | number[] the same as (string | number)[]?

No. string | number[] means either a single string or an array of numbers. (string | number)[] means an array containing strings, numbers, or both.

Are readonly arrays different?

Yes. readonly string[] and ReadonlyArray<string> prevent array modification through that reference.

Why do I see both styles in real projects?

Because both are valid. Different teams, style guides, and developers prefer different syntax.

Take Quiz

Mini Project

Description

Create a small TypeScript module that stores and prints a list of products. The project demonstrates that Product[] and Array<Product> can both be used to describe arrays of objects, and shows how typed arrays make iteration and property access safer.

Goal

Build a typed product list and print formatted product information using both array syntaxes.

Requirements

  • Define a Product type with id, name, and price properties.
  • Create one product list using Product[].
  • Create another product list using Array<Product>.
  • Write a function that accepts a typed array of products and logs each product.
  • Show that both array declarations work with the same function.
Take Quiz

Keep learning

Related questions

View more