Objetos no TypeScript
Assim como no JavaScript, além dos tipos de dados simples, é possível criar objetos que consistem em outros objetos e dados primitivos. Por exemplo:
let person = { name: "Tom", age: 23 };
console.log(person.name);
// Alternativa para acessar a propriedade
console.log(person["name"]);No entanto, embora este seja essencialmente o mesmo objeto que poderíamos usar em JavaScript, devido à tipagem estática do TypeScript, há algumas restrições. Por exemplo, se tivermos o seguinte código:
let person = { name: "Tom", age: 23 };
person = { name: "Bob" }; // Erro!Na segunda linha, ocorrerá um erro, pois o compilador, depois da primeira linha, assume que o objeto person terá duas propriedades: name e age, que são do tipo string e number, respectivamente. Assim, a variável person é do tipo { name: string; age: number }. Podemos especificar isso explicitamente:
let person: { name: string; age: number } = { name: "Tom", age: 23 };
console.log(person.name);Dessa forma, podemos atribuir a essa variável outro objeto, desde que corresponda ao tipo { name: string; age: number }, como no exemplo a seguir:
let person = { name: "Tom", age: 23 };
person = { name: "Bob", age: 35 }; // CorretoPropriedades Opcionais
No TypeScript, é possível definir propriedades opcionais. Para isso, basta adicionar o símbolo de interrogação ? após o nome da propriedade:
let person: { name: string; age?: number }; // A propriedade age é opcionalNeste caso, a propriedade age é opcional, então não é necessário fornecer um valor para ela:
let person: { name: string; age?: number };
person = { name: "Tom", age: 23 };
console.log(person.name); // Tom
person = { name: "Bob" }; // Correto, a propriedade age é opcional
console.log(person.name); // BobAo acessar uma propriedade não definida, será retornado undefined:
let person: { name: string; age?: number } = { name: "Tom", age: 23 };
console.log(person.age); // 23
person = { name: "Bob" };
console.log(person.age); // undefinedPor isso, ao trabalhar com propriedades opcionais, é recomendável verificar se o valor é undefined antes de utilizá-lo:
let person: { name: string; age?: number } = { name: "Tom", age: 36 };
if (person.age !== undefined) {
console.log(person.age);
}Objetos em Funções
Funções podem aceitar objetos como parâmetros e também podem retornar objetos. Nesses casos, é necessário especificar o tipo do objeto tanto para os parâmetros quanto para o retorno. Exemplo de um objeto como parâmetro:
function printUser(user: { name: string; age: number }) {
console.log(`name: ${user.name} age: ${user.age}`);
}
let tom = { age: 36, name: "Tom" };
printUser(tom);Aqui, o parâmetro user da função printUser é do tipo { name: string; age: number }, ou seja, um objeto com duas propriedades, name do tipo string e age do tipo number.
O objeto passado como parâmetro pode conter mais propriedades do que o esperado, desde que contenha as propriedades necessárias:
function printUser(user: { name: string; age: number }) {
console.log(`name: ${user.name} age: ${user.age}`);
}
let bob = { name: "Bob", age: 44, isMarried: true };
printUser(bob);Aqui, a variável bob tem o tipo { name: string; age: number; isMarried: boolean }, mas ainda assim é compatível com o tipo { name: string; age: number }.
Objeto como Resultado de Função
Também é possível definir um objeto como o valor de retorno de uma função:
function defaultUser(): { name: string; age: number } {
return { name: "Tom", age: 37 };
}
let user = defaultUser();
console.log(`name: ${user.name} age: ${user.age}`);Operador in
O operador in verifica se uma determinada propriedade existe em um objeto. Ele retorna true se a propriedade estiver presente no objeto, e false caso contrário. Exemplo:
let tom: { name: string; age?: number } = { name: "Tom", age: 23 };
let bob: { name: string; age?: number } = { name: "Bob" };
function printUser(user: { name: string; age?: number }) {
if ("age" in user) {
console.log(`Name: ${user.name} Age: ${user.age}`);
} else {
console.log(`Name: ${user.name}`);
}
}
printUser(tom);
printUser(bob);Neste exemplo, a função printUser() aceita um objeto do tipo { name: string; age?: number }, ou seja, a propriedade age pode estar presente ou não. Usamos o operador in para verificar se a propriedade existe:
if ("age" in user) {...}O nome da propriedade é passado como uma string.
Desestruturação de Objetos
Se uma função recebe um objeto como parâmetro, o TypeScript permite desestruturar automaticamente suas propriedades:
function printUser({ name, age }: { name: string; age: number }) {
console.log(`name: ${name} age: ${age}`);
}
let tom = { name: "Tom", age: 36 };
printUser(tom);Aqui, a função printUser() desestrutura automaticamente o objeto passado como parâmetro, separando suas propriedades name e age em variáveis. O importante é que os nomes dessas variáveis correspondam aos nomes das propriedades do objeto.
Algumas propriedades podem ser opcionais:
function printUser({ name, age }: { name: string; age?: number }) {
if (age !== undefined) {
console.log(`name: ${name} age: ${age}`);
} else {
console.log(`name: ${name}`);
}
}
let tom = { name: "Tom" };
printUser(tom); // name: Tom
let bob = { name: "Bob", age: 44 };
printUser(bob); // name: Bob age: 44Nesse caso, a propriedade age é opcional, então a função pode ser chamada com ou sem essa propriedade.
Também é possível definir valores padrão para as propriedades:
function printUser({ name, age = 25 }: { name: string; age?: number }) {
console.log(`name: ${name} age: ${age}`);
}
let tom = { name: "Tom" };
printUser(tom); // name: Tom age: 25
let bob = { name: "Bob", age: 44 };
printUser(bob); // name: Bob age: 44Neste exemplo, a propriedade age tem um valor padrão de 25, caso não seja fornecida no objeto passado para a função.