Médio TypeScript

Configuração com readonly e opcionais

Enunciado

Crie um type alias Configuracao que represente as configurações de um aplicativo com:

  • nome: string (readonly)
  • versao: number (readonly)
  • debug: boolean (opcional)
  • porta: number (opcional)

Depois, crie uma função exibirConfiguracao que receba um Configuracao e retorne uma string no formato: "Nome: {nome}, Versão: {versao}, Debug: {debug}, Porta: {porta}". Se debug não for fornecido, use false. Se porta não for fornecida, use 3000.

Além disso, tente modificar a propriedade nome de um objeto Configuracao e observe o erro de compilação (comente a linha).

Requisitos

  • Definir Configuracao com nome e versao readonly.
  • debug e porta devem ser opcionais.
  • A função deve aplicar valores padrão para debug e porta.
  • Comentar uma linha que tente alterar nome e explicar o erro.

Código inicial

// Defina o type alias Configuracao e a função exibirConfiguracao

type Configuracao = {
  // complete aqui
};

function exibirConfiguracao(config: Configuracao): string {
  // complete aqui
}

// Teste
const config1: Configuracao = { nome: 'MeuApp', versao: 1.0 };
const config2: Configuracao = { nome: 'OutroApp', versao: 2.5, debug: true, porta: 8080 };

console.log(exibirConfiguracao(config1));
console.log(exibirConfiguracao(config2));

// Tente modificar config1.nome aqui (comente a linha e explique)

Saída esperada

Nome: MeuApp, Versão: 1, Debug: false, Porta: 3000
Nome: OutroApp, Versão: 2.5, Debug: true, Porta: 8080
Ver dica

Use readonly antes do nome das propriedades. Para os valores padrão, use ?? ou verificação explícita. A linha que tenta modificar nome deve ser comentada para o código compilar.

Mostrar solução
type Configuracao = {
  readonly nome: string;
  readonly versao: number;
  debug?: boolean;
  porta?: number;
};

function exibirConfiguracao(config: Configuracao): string {
  const debug = config.debug ?? false;
  const porta = config.porta ?? 3000;
  return `Nome: ${config.nome}, Versão: ${config.versao}, Debug: ${debug}, Porta: ${porta}`;
}

// Teste
const config1: Configuracao = { nome: 'MeuApp', versao: 1.0 };
const config2: Configuracao = { nome: 'OutroApp', versao: 2.5, debug: true, porta: 8080 };

console.log(exibirConfiguracao(config1));
console.log(exibirConfiguracao(config2));

// Tentativa de modificar readonly: descomente para ver o erro
// config1.nome = 'NovoNome'; // Erro: Cannot assign to 'nome' because it is a read-only property.

Passo a passo

  1. Definimos Configuracao com readonly em nome e versao, impedindo alterações posteriores.
  2. debug e porta são opcionais, então podem ser omitidas na criação do objeto.
  3. Na função exibirConfiguracao, usamos ?? para definir valores padrão: false para debug e 3000 para porta.
  4. Construímos a string com template literals.
  5. Criamos dois objetos: um sem as opcionais e outro com todas.
  6. Chamamos a função e imprimimos os resultados.
  7. Comentamos a linha que tenta alterar nome para mostrar que o TypeScript acusa erro de compilação.

Por que funciona

O readonly faz com que o TypeScript trate a propriedade como imutável após a inicialização. Qualquer tentativa de atribuição gera erro em tempo de compilação. As propriedades opcionais permitem flexibilidade na criação de objetos, e os valores padrão garantem que a função sempre tenha dados válidos para exibir.

Erros comuns

  • Esquecer readonly: se não usar, a propriedade pode ser alterada, contrariando o requisito.
  • Não tratar opcionais: se tentar usar config.debug diretamente sem valor padrão, o TypeScript pode reclamar que é boolean | undefined.
  • Modificar readonly sem comentar: o código não compila. É preciso comentar a linha para que o exemplo rode.

Outra forma de resolver

Usar desestruturação com valores padrão:

const { nome, versao, debug = false, porta = 3000 } = config;
return `Nome: ${nome}, Versão: ${versao}, Debug: ${debug}, Porta: ${porta}`;

É mais limpo, mas cuidado: valores padrão em desestruturação só se aplicam a undefined, não a null.

Saída esperada

Nome: MeuApp, Versão: 1, Debug: false, Porta: 3000
Nome: OutroApp, Versão: 2.5, Debug: true, Porta: 8080