typescript - Por que a interface não me protege neste caso?
interface IA {
readonly a: string;
f(x: string): void;
}
class X implements IA {
a;
f(x) {
this.a = 1;
}
}
let x = new X().a;
Surpreendentemente, este código compila.
- Ele infere o tipo de
X.acomoany, por que é isso? readonlynão parece me proteger de modificar a. Estou usando errado?
Atualizar
https://github.com/Microsoft/TypeScript/issues/11578
Resposta #1
Basicamente devido a qualquer variável não tipada ser implicitamente any. Você pode desativar isso nas opções do compilador:
"noImplicitAny": true
no ponto em que você terá que definir um tipo que possa ser atribuído ao tipo de interface base.
quanto ao somente leitura. está funcionando como esperado:
você precisa entender que existem algumas diferenças entre TypeScript e outras linguagens OO como C#. Nomeadamente que a atribuição de uma variável tipada a outra é toda sobre se o tipo do lado direito intersecta com o tipo do lado esquerdo. ou seja.
let x: X = { a: "hello", f: (x) => { } };
é perfeitamente válido.
Resposta #2
Ele infere X.a como any porque você não especificou o tipo.
Quando sua classe implementa uma interface, ela deve especificar tudo o que a interface definiu, se você não for incluir o membro a:
class X implements IA {
f(x) {
this.a = 3;
}
}
Você receberá:
Classe 'X' implementa incorretamente a interface 'IA'.
A propriedade 'a' está ausente no tipo 'X'
E
A propriedade 'a' não existe no tipo 'X'
Você não recebe nenhum erro por não incluir o tipo para a, e isso é porque ele é automaticamente any e isso satisfaz o compilador.
Você pode instruir o compilador a checar isso usando noImplicitAny nas opções do compilador:
Gerar erro em expressões e declarações com um tipo ‘any’ implícito
A parte readonly não é aplicada porque ela é apenas readonly na interface IA, mas não para a classe:
class X implements IA {
a;
f(x) {
(this as IA).a = ""; // Error: Left-hand side of assignment expression cannot be a constant or a read-only property
}
}
E :
class X implements IA {
readonly a;
f(x) {
this.a = ""; // Error: Left-hand side of assignment expression cannot be a constant or a read-only property
}
}

