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:
// 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"];
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
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!)
[] é 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
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
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}`);
});
Saída:
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
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
let readonlyArr2: ReadonlyArray<string> = ["a", "b", "c"];
// and readonly string[] Equivalent
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
// 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
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 ?:
let result: [string, number?] = ["Success"];
console.log(result[0]); // "Success"
console.log(result[1]); // undefined(Optional elements may be omitted.)
[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:
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
// 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`);
}
Saída:
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
// 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
(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
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
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
- Conjuntos de dados semelhantes (listas de usuários, listas de pontuação, listas de itens de configuração)
- Número indeterminado de elementos
- São necessárias operações como percorrimento, pesquisa e classificação
(2) Quando usar tuplas
- Pequenos conjuntos de dados com comprimentos e estruturas fixos (coordenadas
[x, y], pares chave-valor[key, value]) - As funções retornam vários valores
- Estruturas simples com apenas dois ou três elementos (use objetos ou interfaces para estruturas mais complexas)
(3) Quando usar uma matriz somente leitura
- Parâmetros de função — uma promessa de não modificar o array passado como parâmetro
- Configuração constante — Prevenção de alterações acidentais
- Valor de retorno da API — informa ao usuário que os dados são imutáveis
▶ Exemplo: Exercício abrangente — Gestão das notas dos alunos
// 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)`);
Saída:
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, poisuser.nameé muito mais legível do queuser[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[]enumber[]? R:number[]pode ser atribuído areadonly number[](o endurecimento do tipo é seguro), masreadonly number[]não pode ser atribuído anumber[](o afrouxamento do tipo resultaria na perda da proteção de somente leitura). Isso é semelhante à direção de atribuição paraconst— 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étodospush/poppodem ser executados no modo estrito sem passar pela verificação de tipos. Recomenda-se usar tuplasreadonly(readonly [string, number]) para impedir completamente qualquer modificação.
📖 Resumo
- Existem duas maneiras de escrever tipos de matriz:
type[](recomendado) eArray<type>; ambas têm exatamente o mesmo efeito. readonly type[]eReadonlyArray<type>criam matrizes somente leitura; não é possível adicionar, excluir ou modificar elementos nelas.- Uma tupla
[type1, type2, ...]é um tipo especial de matriz de comprimento fixo, em que cada elemento é de um tipo específico. - As tuplas suportam desestruturação, elementos opcionais (
type?), elementos restantes (...type[]) e rótulos ([name: string]) (A | B)[](matriz de tipo união) eA[] | B[](matriz de tipos de união) têm significados completamente diferentes
📝 Exercícios
- Problema básico (Dificuldade ⭐): Crie um array
string[]para armazenar os nomes de cinco linguagens de programação e, em seguida, useforEachpara percorrê-los e exibi-los. Depois, escreva uma versão somente leiturareadonly string[], tente modificá-la e observe a mensagem de erro. - 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"]. - 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.