Interfaces - TypeScript
Interfaces de Objetos
Uma interface define as propriedades e métodos que um objeto deve implementar. Em outras palavras, uma interface é a definição de um tipo de dados personalizado, mas sem implementação. Neste caso, as interfaces em TypeScript são semelhantes às interfaces nas linguagens Java e C#. As interfaces são definidas usando a palavra-chave interface
interface IUser {
id: number;
name: string;
}
A interface entre chaves define duas propriedades: id
number
name
let employee: IUser = {
id: 1,
name: "Tom"
};
console.log("id: ", employee.id);
console.log("name: ", employee.name);
Essencialmente, employee
IUser
employee
IUser
employee
employee
IUser
employee
id
name
Os parâmetros de métodos e funções também podem representar interfaces:
interface IUser {
id: number;
name: string;
}
let employee: IUser = {
id: 1,
name: "Alice"
};
function printUser(user: IUser): void {
console.log("id: ", user.id);
console.log("name: ", user.name);
}
printUser(employee);
Neste caso, o argumento que é passado para a função deve ser um objeto ou classe que implementa a interface correspondente.
E também é possível retornar objetos de uma interface:
interface IUser {
id: number;
name: string;
}
function buildUser(userId: number, userName: string): IUser {
return { id: userId, name: userName };
}
let newUser = buildUser(2, "Bill");
console.log("id: ", newUser.id);
console.log("name: ", newUser.name);
Propriedades Opcionais e Propriedades Somente Leitura
Ao definir uma interface, podemos especificar algumas propriedades como opcionais usando o ponto de interrogação. Tais propriedades não precisam ser necessariamente implementadas:
interface IUser {
id: number;
name: string;
age?: number;
}
let employee: IUser = {
id: 1,
name: "Alice",
age: 23
};
let manager: IUser = {
id: 2,
name: "Tom"
};
A propriedade age
IUser
Além disso, uma interface pode conter propriedades somente leitura, cujo valor não pode ser alterado. Tais propriedades são definidas com a palavra-chave readonly
interface Point {
readonly x: number;
readonly y: number;
}
let p: Point = { x: 10, y: 20 };
console.log(p);
// p.x = 5; // Erro - propriedade somente leitura
Definição de Métodos
Além das propriedades, as interfaces podem definir funções:
interface IUser {
id: number;
name: string;
sayWords(words: string): void;
}
let employee: IUser = {
id: 1,
name: "Alice",
sayWords: function(words: string): void {
console.log(`${this.name} diz "${words}"`);
}
};
employee.sayWords("Olá, como vai?");
interface IUser {
id: number;
name: string;
sayWords(words: string): void;
}
let employee: IUser = {
id: 1,
name: "Alice",
sayWords: function(words: string): void {
console.log(`${this.name} diz "${words}"`);
}
};
employee.sayWords("Olá, como vai?");
Novamente, um objeto que implementa a interface é obrigado a implementar a função definida na interface com o mesmo conjunto de parâmetros e o mesmo tipo de resultado. Neste caso, a função sayWords()
Interfaces de Classes
As interfaces podem ser implementadas não apenas por objetos, mas também por classes. Para isso, utiliza-se a palavra-chave implements
interface IUser {
id: number;
name: string;
getFullName(surname: string): string;
}
class User implements IUser {
id: number;
name: string;
age: number;
constructor(userId: number, userName: string, userAge: number) {
this.id = userId;
this.name = userName;
this.age = userAge;
}
getFullName(surname: string): string {
return this.name + " " + surname;
}
}
let tom = new User(1, "Tom", 23);
console.log(tom.getFullName("Simpson"));
A classe User implementa a interface IUser
User
IUser
Além disso, o objeto tom é tanto um objeto User
IUser
let tom: IUser = new User(1, "Tom", 23);
// ou
let tom: User = new User(1, "Tom", 23);
Extensão de Interface
O TypeScript permite adicionar novos campos e métodos a uma interface simplesmente declarando a interface com o mesmo nome e definindo nela os campos e métodos necessários. Por exemplo:
interface IUser {
id: number;
name: string;
}
interface IUser {
age: number;
}
let employee: IUser = {
id: 1,
name: "Alice",
age: 31
};
function printUser(user: IUser): void {
console.log(`id: ${user.id} name: ${user.name} age: ${user.age}`);
}
printUser(employee);
Neste caso, a primeira definição da interface IUser
id
name
age
id
name
age
Herança de Interfaces
As interfaces, assim como as classes, podem ser herdadas:
interface IMovable {
speed: number;
move(): void;
}
interface ICar extends IMovable {
fill(): void;
}
class Car implements ICar {
speed: number;
move(): void {
console.log("O carro está se movendo a " + this.speed + " km/h");
}
fill(): void {
console.log("Abastecendo o carro com combustível");
}
}
let auto = new Car();
auto.speed = 60;
auto.fill();
auto.move();
Após a herança, a interface ICar
IMovable
Car
ICar
IMovable
Interfaces de Função
Interfaces de função contêm a definição do tipo de uma função. Elas devem ser implementadas por um objeto que representa uma função desse tipo:
interface FullNameBuilder {
(name: string, surname: string): string;
}
let simpleBuilder: FullNameBuilder = function (name: string, surname: string): string {
return "Mr. " + name + " " + surname;
};
let fullName = simpleBuilder("Bob", "Simpson");
console.log(fullName); // Mr. Bob Simpson
Aqui, a interface FullNameBuilder
simpleBuilder
FullNameBuilder
Interfaces de Arrays
Interfaces de arrays descrevem objetos que podem ser acessados por índice, como em arrays:
interface StringArray {
[index: number]: string;
}
let phones: StringArray;
phones = ["iPhone 7", "HTC 10", "HP Elite x3"];
let myPhone: string = phones[0];
console.log(myPhone);
Aqui, a interface StringArray
StringArray
number
string
No exemplo acima, o índice é do tipo number
string
interface Dictionary {
[index: string]: string;
}
let colors: Dictionary = {};
colors["red"] = "#ff0000";
colors["green"] = "#00ff00";
colors["blue"] = "#0000ff";
console.log(colors["red"]);
Interfaces Híbridas
As interfaces podem combinar diferentes estilos e podem ser aplicadas tanto à definição de um objeto quanto de uma função:
interface PersonInfo {
(name: string, surname: string): void;
fullName: string;
password: string;
authenticate(): void;
}
function personBuilder(): PersonInfo {
let person = <PersonInfo>function (name: string, surname: string): void {
person.fullName = name + " " + surname;
};
person.authenticate = function () {
console.log(person.fullName + " está se autenticando com a senha " + person.password);
};
return person;
}
let tom = personBuilder();
tom("Tom", "Simpson");
tom.password = "qwerty";
tom.authenticate();
O tipo de função definido em uma interface híbrida geralmente atua como um construtor de objetos. Neste caso, esse construtor tem o tipo (name: string, surname: string): void
A função que representa essa interface (neste exemplo, a função personBuilder