typescript - É possível definir uma classe que implemente uma interface sem implementação?
É possível definir uma classe que tenha variáveis de interface sem implementação em TypeScript?
Por exemplo:
interface ITask {
id: number;
title: string;
}
class Task implements ITask {
// without implementation
}
O código acima causará um erro como este:
Type 'Task' is missing the following properties from type 'Task', ...
Eu também tentei o seguinte código, mas ele também causou um erro:
class Task extends ITask {
// without implementation
}
TypeError: Class extends value undefined is not a constructor or null
Estou fazendo esta pergunta porque quero gerar classes a partir de interfaces automaticamente, sem alterar nenhuma variável. Eu não quero copiar e colar todas as variáveis.
Resposta #1
Há muita segurança de tipo que o conjunto de opções de compilador --strict oferece. (Se você não está usando, deveria usar.) Parece que você está tentando contornar parte disso e não está claro para mim por que você quer fazer isso. Se você convencer o compilador de que a classe implementou a interface sem realmente fazê-lo, tudo o que você estará fazendo é suprimir avisos do compilador que têm o objetivo de prevenir erros em tempo de execução. Como está, o código a seguir gera avisos do compilador:
const t: ITask = new Task(); // error here
t.id.toFixed(2);
o que é algo bom, porque em tempo de execução, t.id será undefined, então t.id.toFixed() lançará uma exceção. Se você forçar Task implements ITask a funcionar, então não receberia avisos do compilador, mas ainda assim receberia um erro em tempo de execução.
Se você realmente quiser fazer isso, pode usar a mesclagem de declarações para reabrir a interface de instância de Task e fazê-la estender ITask:
interface Task extends ITask { } // merging
class Task implements ITask {
}
Agora não há erro, mas é claro que você encontra o mesmo problema aqui:
const t = new Task();
t.id.toFixed() // compiles without error
Se você quiser estar seguro, você poderia fazer Task implementar Partial<ITask> usando o tipo de utilitário Partial<T> para tornar as propriedades de ITask opcionais:
interface Task extends Partial<ITask> { }
class Task implements Partial<ITask> {
}
E agora o compilador esperará que uma Task possivelmente tenha esses campos, mas você precisa verificá-los quanto a nulidade antes de usá-los, como usando o operador de encadeamento opcional (?.):
const t = new Task();
t.id.toFixed() // compiler error now
t.id?.toFixed(); // okay
Link do playground para o código
Resposta #2
Você pode usar essa abordagem
interface IUser {
name: string;
email: string;
phone: string;
}
interface User extends IUser {}
class User {
constructor(user: IUser) {
Object.assign(this, user);
}
getFullName() {
return this.name;
}
}
const userData: IUser = {
email: "[email ",
phone: "1234567890",
name: "John Doe",
};
const user = new User(userData);
console.log(user.email); // [email
console.log(user.getFullName()); // John Doe
