Pesquisa de site

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.a como any, por que é isso?
  • readonly nã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
    }
}