Imutabilidade <vs> tipo de segurança
Meu projeto mais recente me abençoou com a chance de trabalhar com Angular2 e Typescript, isso é uma grande mudança em relação a escrever no babel transpilado ES6 como estou acostumado.
Os tipos fornecem ferramentas fortes – Webstorm 12 no meu caso – parece “saber” o que estou fazendo e oferece grande ajuda, sugerindo autocompletar e marcando meus erros.
Arquitetura de fluxo de dados de front-end atual, como Redux e @ ngrx / store beneficia muito para o uso de estruturas de dados Imutáveis.
No entanto, isso quebra a capacidade do Typescript de sugerir nomes de propriedades.
o choque de titãs
vamos examinar:
um hash simples declarado aqui
const myHash = {
property:"value"
}
fará o IDE sugerir a propriedade interna ao escrever a referência do objeto (mesmo sem um tipo),
então, quando você escrever myHash.
você obterá um menu suspenso no qual “propriedade” será a primeira opção
é claro que você pode obter resultados ainda melhores
interface myHash{
property:string
}
const myHash<myHash> = {property:"value"}
//in use
myHash.property = 5;
//the IDE will mark the above line as error (and indeed the TS compiler will error too)
Mas quando você introduz a imutabilidade, o uso de = para definir valores é limitado a atribuir novas instâncias
const myHash = Immutable.fromJS({property:"value"})
myHash.property = 5 // Error : immutable can not be changed
//even worse - myHash does not have autocomplete for .property.... it does not have this property
console.log(myHash.property) // undefined
isso ocorre porque Immutable.fromJS cria um immutable.Map ao usá-lo com um argumento POJO de origem (objeto javascript antigo simples)
a maneira certa de usá-lo é esta:
myHash.get('property'); // value
let newValueHash = myHash.set('property','newValue');
usar o nome da propriedade como argumento de string elimina a ajuda do typescript e de todas as novas ferramentas IDE baseadas nele.
Grave para o resgate
Um comportamento muito melhor pode surgir usando Immutable.Record:
const myHashRecord = new Immutable.Record({property:'defaultValue'})
let myHash = new myHashRecord();
console.log(myHash.property) // defaultValue
//notice that the property can be accessed like in POJO
//but for setting new value we need to use it like before in the Map's case
myHash.property = 555; //Error
let newHashValue = myHash.set('property'','newValue') //works
portanto, isso nos ajuda em relação ao preenchimento automático, mas não:
1. nos ajuda com a necessidade de escrever os nomes das propriedades como strings no caso de definir novas propriedades
2. nos protege de usar o tipo errado ao definir um novo valor
Eu descobri que uma combinação entre um Immutable Record e uma Typcript Class pode pelo menos nos dar o segundo ponto feito, ela nos faz escrever nossa lista de propriedades duas vezes, mas eu acho que vale a pena digitar.
let demoRecord = Immutable.Record({
property:'defaultValue',
index:0,
works:true,
valueList:Immutable.List([])
});
export class Demo extends demoRecord {
property:string;
index:number;
truth:boolean;
valueList:Immutable.List<YourMoreComplexTypeHere>
}
let demo = new Demo();
agora, ao escrever demo. o IDE irá sugerir a você suas propriedades, bem como os métodos de protótipo do Registro, como .set, .toJS etc.,
mas o IDE também saberá que a propriedade “index” é um número e que “true” é um booleano.
Claro, você pode usar tipos mais complexos com base em suas definições de tipo e interface.
Mais pensamentos
a biblioteca Immutable.js está vindo do Facebook, Typescript é tecnologia da Microsoft, construímos sobre os ombros de gigantes aqui, eu me pergunto por que temos que fazer tais truques para fazer os dois funcionarem bem juntos, e isso ainda não é perfeito.
há um problema sobre esse assunto no repo do Facebook , lembro-me de ter visto um também no repo da Microsoft, mas não consegui encontrá-lo hoje.
Existem também outras bibliotecas Immutable como alguns dos comentários sobre esse tópico apontam, a imutabilidade pode ser alcançada via Object.defineProperty escrevendo getters apenas, ou pode-se usar geratos de código de tipificação como ts-immutable, mas eu sugiro que o futuro deve ser mais simples neste caso
, ficarei muito feliz em ouvir sua opinião sobre o assunto.