Desafio TypeScript
Classe genérica Pilha
Enunciado
Implemente uma classe genérica Pilha<T> que armazena elementos em um array interno. A classe deve ter os métodos push(item: T): void, pop(): T | undefined e peek(): T | undefined. O construtor pode receber um array inicial opcional. Use genéricos para garantir que todos os elementos sejam do mesmo tipo.
Requisitos
- A classe deve se chamar
Pilhae ser genérica emT. - Deve ter um array privado
itens: T[]. - O construtor deve aceitar um array opcional
itensIniciais?: T[]. pushadiciona um item ao final.popremove e retorna o último item, ouundefinedse vazia.peekretorna o último item sem remover, ouundefinedse vazia.
Código inicial
// Implemente a classe Pilha<T>
class Pilha {
// ...
}
const pilha = new Pilha<number>([1, 2]);
pilha.push(3);
console.log(pilha.peek()); // 3
console.log(pilha.pop()); // 3
console.log(pilha.pop()); // 2
console.log(pilha.pop()); // 1
console.log(pilha.pop()); // undefined
Saída esperada
3
3
2
1
undefined
Ver dica
Use private itens: T[] e inicialize no construtor. Para pop e peek, verifique se o array está vazio antes de acessar o último elemento.
Mostrar solução
// Classe genérica que implementa uma pilha (LIFO)
class Pilha<T> {
private itens: T[];
// Construtor aceita um array inicial opcional
constructor(itensIniciais?: T[]) {
this.itens = itensIniciais ?? [];
}
// Adiciona um item ao topo da pilha
push(item: T): void {
this.itens.push(item);
}
// Remove e retorna o item do topo, ou undefined se vazia
pop(): T | undefined {
return this.itens.pop();
}
// Retorna o item do topo sem remover, ou undefined se vazia
peek(): T | undefined {
return this.itens[this.itens.length - 1];
}
}
// Exemplo de uso
const pilha = new Pilha<number>([1, 2]);
pilha.push(3);
console.log(pilha.peek()); // 3
console.log(pilha.pop()); // 3
console.log(pilha.pop()); // 2
console.log(pilha.pop()); // 1
console.log(pilha.pop()); // undefined
Passo a passo
- Declaramos
class Pilha<T>com o parâmetro de tipoT. - A propriedade
private itens: T[]armazena os elementos; é privada para encapsulamento. - O construtor recebe
itensIniciais?: T[]e usa??para inicializar com array vazio se não fornecido. - O método
pushrecebeitem: Te o adiciona ao final do array comthis.itens.push(item). - O método
popusathis.itens.pop(), que já retornaT | undefined(undefined se vazio). - O método
peekacessathis.itens[this.itens.length - 1]; se o array estiver vazio, o índice é-1e o acesso retornaundefined. - No uso,
new Pilha<number>([1, 2])cria uma pilha de números; o TypeScript impede adicionar strings.
Por que funciona
A classe genérica Pilha<T> permite criar pilhas de qualquer tipo, mantendo a consistência: todos os métodos usam T. O array interno itens: T[] garante que apenas valores do tipo T sejam armazenados. A inferência de tipos também funciona: se você escrever new Pilha([1, 2]), T será inferido como number. O uso de ?? no construtor lida com a ausência do array inicial sem erros.
Erros comuns
- Não tipar o array como
T[]:private itens = []infereany[], perdendo a segurança. Useprivate itens: T[]. - Acessar
this.itens[this.itens.length - 1]sem verificar vazio: em arrays vazios, o índice é-1e o acesso retornaundefined, o que é aceitável aqui, mas se você tentar usar o valor sem checar, pode ter erros em tempo de execução. O retornoT | undefinedjá cobre isso. - Esquecer de passar o tipo genérico na instanciação:
new Pilha([1, 2])infereTcomonumber, mas se você quiser forçar outro tipo, usenew Pilha<string>(). - Usar
popem array vazio sem tratarundefined: o retorno éT | undefined, então o compilador exige verificação antes de usar comoT.
Outra forma de resolver
Você pode usar uma interface genérica para definir o contrato e implementar a classe:
interface IPilha<T> {
push(item: T): void;
pop(): T | undefined;
peek(): T | undefined;
}
class Pilha<T> implements IPilha<T> { /* ... */ }
É preferível quando você quer desacoplar a implementação da interface, facilitando testes e substituições.
Saída esperada
3
3
2
1
undefined