TypeScript: Matrizes e tuplas no TypeScript

Última atualização: 2026-08-26

Arrays e tuplas são os dois tipos de coleção mais comumente usados no TypeScript — um array é uma “coleção de valores do mesmo tipo”, enquanto uma tupla é um tipo especial de array com “comprimento fixo e tipos específicos para cada elemento”.

1. Tipos de matrizes

(1) Duas sintaxes de anotação

O TypeScript oferece duas formas equivalentes de definir tipos de matriz:

TYPESCRIPT
// Method 1:Type + square brackets(Recommendations,More intuitive)
let numbers: number[] = [1, 2, 3, 4, 5];
let names: string[] = ["Charlie", "Diana", "Eric"];

// Method 2:Generic Arrays(Commonly used in generic scenarios)
let scores: Array<number> = [90, 85, 95];
let items: Array<string> = ["a", "b", "c"];
📌 Recomendação: Use a sintaxe type[] no desenvolvimento diário — ela é mais concisa. A sintaxe genérica Array<T> é mais clara ao lidar com certos tipos complexos ou quando usada com funções genéricas.

(2) Inferência de tipo de matriz

TYPESCRIPT
let arr1 = [1, 2, 3];           // Inferred as number[]
let arr2 = ["a", "b", "c"];     // Inferred as string[]
let arr3 = [1, "hello", true];  // Inferred as (number | string | boolean)[]
let arr4 = [];                  // Inferred as any[](Danger!)
🔥 Erro comum: Um array vazio [] é interpretado como any[], e atribuições subsequentes de tipos diferentes não resultarão em erro. No modo estrito, recomenda-se rotulá-lo explicitamente como let arr4: number[] = [].

(3) Matrizes multidimensionais

TYPESCRIPT
let matrix: number[][] = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

// Accessing Elements
console.log(matrix[0][1]);  // 2

// Three-dimensional array
let cube: number[][][] = [[[1]]];

▶ Exemplo: Operações básicas com matrizes

TYPESCRIPT
let fruits: string[] = ["Apple", "Banana", "Orange"];

// Add an element
fruits.push("Grapes");          // Add at the end
fruits.unshift("Strawberries");       // Add at the beginning

// Delete Element
let last = fruits.pop();      // Delete the end,Back "Grapes"
let first = fruits.shift();   // Delete the beginning,Back "Strawberries"

// Search
let index = fruits.indexOf("Banana");  // 0(The strawberries and grapes were removed.,The banana came in first)

// Iterate
fruits.forEach((fruit, i) => {
  console.log(`${i}: ${fruit}`);
});
▶ Experimente

Saída:

TEXT 📖 Somente leitura
0: Banana
1: Orange


2. Matrizes somente leitura

Matrizes somente leitura não podem ser modificadas — não é permitido adicionar, excluir ou alterar elementos:

(1) modificador readonly

TYPESCRIPT
let readonlyArr: readonly number[] = [1, 2, 3];

// readonlyArr[0] = 10;     // ❌ Read-only,Cannot be modified
// readonlyArr.push(4);     // ❌ Read-only,Cannot be added
// readonlyArr.length = 0;  // ❌ Read-only,The length cannot be changed

let normalArr: number[] = [1, 2, 3];
readonlyArr = normalArr;    // ✅ A regular array can be assigned to a read-only array
// normalArr = readonlyArr; // ❌ A read-only array cannot be assigned to a regular array.

(2) ReadonlyArray genérico

TYPESCRIPT
let readonlyArr2: ReadonlyArray<string> = ["a", "b", "c"];
// and readonly string[] Equivalent
💡 Objetivo: Usar um array somente leitura como parâmetro de função deixa claro para quem chama a função que “esta função não modificará seu array”:

TYPESCRIPT
function printItems(items: readonly string[]) {
  items.forEach(item => console.log(item));
  // items.push("new");  // ❌ Compilation Error——The function is guaranteed not to be modified
}

let myItems = ["a", "b"];
printItems(myItems);  // Safety——myItems Will not be modified


3. Tipo tupla

Uma tupla é uma matriz com “comprimento fixo e tipos específicos para cada elemento” — pode ser considerada uma versão simplificada de uma “estrutura fixa nomeada”.

(1) Sintaxe básica

TYPESCRIPT
// Defining Tuples:[Type1, Type2, ...]
let user: [string, number] = ["Charlie", 20];

// Access by Index
console.log(user[0]);  // "Charlie"(string Type)
console.log(user[1]);  // 20(number Type)

// Assignments must match in type and length
// user = [20, "Charlie"];  // ❌ Type order does not match
// user = ["Charlie"];      // ❌ Not long enough
// user = ["Charlie", 20, true];  // ❌ Exceeds the length limit

(2) A diferença entre tuplas e matrizes

Característica Matriz number[] Tupla [string, number]
Comprimento Qualquer Fixo
Tipo de elemento Todos iguais Pode variar de acordo com a posição
Acesso Todos os elementos são do mesmo tipo Cada índice tem um tipo específico
Casos de uso Conjuntos de dados semelhantes Conjuntos de dados pequenos com estrutura fixa

(3) Desestruturação de tuplas

TYPESCRIPT
let pair: [string, number] = ["Apple", 5];

let [fruit, count] = pair;
console.log(fruit);   // "Apple"
console.log(count);   // 5

// Including remaining elements
let record: [string, number, ...boolean[]] = ["Test", 100, true, false, true];
let [name, score, ...flags] = record;
console.log(name);    // "Test"
console.log(score);   // 100
console.log(flags);   // [true, false, true]

(4) Elementos opcionais

Os elementos opcionais em uma tupla podem ser marcados com ?:

TYPESCRIPT
let result: [string, number?] = ["Success"];

console.log(result[0]);  // "Success"
console.log(result[1]);  // undefined(Optional elements may be omitted.)
⚠️ Observação: Os elementos opcionais só podem aparecer no final. [string?, number] é inválido — nenhum elemento obrigatório pode vir após um elemento opcional.

(5) Tuplas marcadas

O TypeScript 4.0 introduziu rótulos de tupla, que tornam a semântica de cada posição mais clara:

TYPESCRIPT
let user: [name: string, age: number] = ["Charlie", 20];
let point: [x: number, y: number, z?: number] = [1.0, 2.5];

// Tags are only for document purposes,Does not affect the type——But the code's readability has improved significantly
function getRange(): [min: number, max: number] {
  return [0, 100];
}

let [min, max] = getRange();
console.log(`Scope:${min} - ${max}`);  // Scope:0 - 100

▶ Exemplo: Tuplas como valores de retorno de função

TYPESCRIPT
// Tuples are ideal for representing the return values of functions."Multiple values"
function divide(a: number, b: number): [quotient: number, remainder: number] {
  return [Math.floor(a / b), a % b];
}

let [quotient, remainder] = divide(17, 5);
console.log(`Quotient:${quotient},Remainder:${remainder}`);  // Quotient:3,Remainder:2

// A tuple represents a key-value pair
function entries(obj: Record<string, number>): [string, number][] {
  return Object.entries(obj) as [string, number][];
}

let scores = { Chinese Language: 90, Mathematics: 95, English: 88 };
for (let [subject, score] of entries(scores)) {
  console.log(`${subject}:${score}pts`);
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
Quotient:3,Remainder:2
Chinese Language:90pts
Mathematics:95pts
English:88pts


4. Operações de ordem superior em matrizes

(1) Matrizes com tipos de união versus matrizes de tipos de união

TYPESCRIPT
// Union Type Arrays:Each element in the array can be number or string
let mixed: (number | string)[] = [1, "two", 3, "four"];

// Union Types for Arrays:Either... or number[],Either... or string[]
let uniform: number[] | string[] = [1, 2, 3];   // ✅
uniform = ["a", "b", "c"];                        // ✅
// uniform = [1, "two"];                          // ❌ Do not mix
🔥 Erro comum: (number | string)[] e number[] | string[] têm significados completamente diferentes! O primeiro se refere a uma “matriz mista”, enquanto o segundo se refere a uma “matriz puramente numérica ou puramente de strings”.

(2) Segurança de tipos dos métodos de matriz

TYPESCRIPT
let nums: number[] = [3, 1, 4, 1, 5];

// sort An explicit comparison function is required,Otherwise, sort by string
nums.sort((a, b) => a - b);     // ✅ Number Sorting:[1, 1, 3, 4, 5]

// map Automatic Inference of Return Types
let doubled = nums.map(n => n * 2);   // Inferred as number[]
let asStrings = nums.map(String);      // Inferred as string[]

// filter Automatically Infer Element Types
let big = nums.filter(n => n > 2);    // Inferred as number[]

(3) Desempacotamento de matrizes e tipos

TYPESCRIPT
let a: number[] = [1, 2];
let b: number[] = [3, 4];
let merged: number[] = [...a, ...b];  // [1, 2, 3, 4]

// Tuple Unpacking
let prefix: [string, number] = ["No.", 0];
let full: [string, number, ...number[]] = [...prefix, 1, 2, 3];
// full = ["No.", 0, 1, 2, 3]


5. Opções no desenvolvimento propriamente dito

(1) Quando usar matrizes

(2) Quando usar tuplas

(3) Quando usar uma matriz somente leitura

▶ Exemplo: Exercício abrangente — Gestão das notas dos alunos

TYPESCRIPT
// Represented as a tuple [Subject, Fractions]
type Score = [subject: string, score: number];

// Storing Multiple Grades in an Array
let scores: Score[] = [
  ["Chinese Language", 92],
  ["Mathematics", 88],
  ["English", 95],
  ["Physics", 78],
  ["Chemistry", 85]
];

// Calculate the average score
function average(scores: readonly Score[]): number {
  let total = scores.reduce((sum, [, score]) => sum + score, 0);
  return total / scores.length;
}

// Find the subject with the highest score
function topSubject(scores: readonly Score[]): Score {
  return scores.reduce((best, current) =>
    current[1] > best[1] ? current : best
  );
}

console.log("Average Score:" + average(scores).toFixed(1));
let [subject, score] = topSubject(scores);
console.log(`Subject with the Highest Score:${subject}(${score}pts)`);
▶ Experimente

Saída:

TEXT 📖 Somente leitura
Average Score:87.6
Subject with the Highest Score:English(95pts)

❓ Perguntas Frequentes

P: Qual é a diferença entre tuplas e objetos comuns? Quando cada um deve ser usado? R: As tuplas são acessadas por índice (tuple[0]), enquanto os objetos são acessados por chave (obj.name). Tuplas são adequadas para estruturas simples e fixas com 2 a 3 elementos (como coordenadas ou pares chave-valor); use objetos ou interfaces quando houver mais de 3 elementos ou quando a semântica for complexa, pois user.name é muito mais legível do que user[0].

P: Qual é exatamente a diferença entre (número | string)[] e número[] | string[]? R: (number | string)[] é um array em que “cada elemento pode ser um número ou uma string” — permitindo uma mistura, como [1, "a", 2]. number[] | string[] é um array em que “todo o array é composto apenas por números ou apenas por strings” — tipos mistos não são permitidos, portanto [1, "a"] é inválido. O último é uma união de dois tipos de array, não um array do tipo união.

P: Qual é a relação de atribuição entre readonly number[] e number[]? R: number[] pode ser atribuído a readonly number[] (o endurecimento do tipo é seguro), mas readonly number[] não pode ser atribuído a number[] (o afrouxamento do tipo resultaria na perda da proteção de somente leitura). Isso é semelhante à direção de atribuição para const — ela só pode ocorrer de um tipo menos restrito para um mais restrito.

P: Por que as operações push/pop em tuplas não passam por verificação de tipo? R: Essa é uma falha de projeto conhecida no TypeScript. O acesso a elementos fora dos limites em tuplas (como tuple[100]) gerará um erro, mas os métodos push/pop podem ser executados no modo estrito sem passar pela verificação de tipos. Recomenda-se usar tuplas readonly (readonly [string, number]) para impedir completamente qualquer modificação.

📖 Resumo

📝 Exercícios

  1. Problema básico (Dificuldade ⭐): Crie um array string[] para armazenar os nomes de cinco linguagens de programação e, em seguida, use forEach para percorrê-los e exibi-los. Depois, escreva uma versão somente leitura readonly string[], tente modificá-la e observe a mensagem de erro.
  2. Problema avançado (Dificuldade ⭐⭐): Defina uma função swap(tuple: [string, number]): [number, string] que utilize uma tupla para trocar as posições e os tipos dos dois elementos da tupla. Por exemplo, swap(["hello", 42]) retorna [42, "hello"].
  3. Problema de desafio (Dificuldade ⭐⭐⭐): Implemente uma função parseCSV(lines: string[]): [header: string[], ...rows: string[][]] que analise um arquivo de texto CSV em tuplas — em que a primeira linha é o cabeçalho e as linhas restantes são os dados. O tipo de retorno deve ser uma tupla marcada com os elementos restantes.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%