1
resposta

[Dúvida] Estou obtendo erros ao implementar decorator @domInjector

Seguindo a aula 5, do módulo 3 de TypeScript. Estou obtendo erros ao implementar decorator @domInjector.

este é o código do decorator:

export function domInjector(seletor: string) {
    return function (target: any, propertyKey: string) {

        console.log(`Modificando prototype ${target.constructor.name}
            e adicionando getter para a propriedade ${propertyKey}`);
        const getter = function () {
            const elemento = document.querySelector(seletor);
            console.log(`buscando elemento do DOM com o seletor 
                ${seletor} para injetar em ${propertyKey}`);
            return elemento;
        }

        Object.defineProperty(
            target, 
            propertyKey, 
            { get: getter }
        );

    }
}

Este é o início do código de negociaçao-contoller onde está sendo implementado o decorator @domInjector:

import { inspect } from "../decorators/inspect.js";
import { logarTempoDeExecucao } from "../decorators/logar-tempo-de-execucao.js";
import { DiasDaSemana } from "../enums/dias-da-semana.js";
import { Negociacao } from "../models/negociacao.js";
import { Negociacoes } from "../models/negociacoes.js";
import { MensagemView } from "../views/mensagem-view.js";
import { NegociacoesView } from "../views/negociacoes-view.js";

export class NegociacaoController {
    @domInjector('#data')
    private inputData: HTMLInputElement;
    @domInjector('#quantidade')
    private inputQuantidade: HTMLInputElement;
    @domInjector('#valor')
    private inputValor: HTMLInputElement;

    private negociacoes = new Negociacoes();
    private negociacoesView = new NegociacoesView('#negociacoesView');
    private mensagemView = new MensagemView('#mensagemView');

    constructor() {
        this.negociacoesView.update(this.negociacoes);
    }

antes de modificar o código para a implementação do @domInjector no constructor havia a declaraçao das variáveis:

export class NegociacaoController {
    private inputData: HTMLInputElement;
    private inputQuantidade: HTMLInputElement;
    private inputValor: HTMLInputElement;
    private negociacoes = new Negociacoes();
    private negociacoesView = new NegociacoesView('#negociacoesView');
    private mensagemView = new MensagemView('#mensagemView');

    constructor() {
        this.inputData = document.querySelector('#data') as HTMLInputElement;
        this.inputQuantidade = document.querySelector('#quantidade') as HTMLInputElement;
        this.inputValor = document.querySelector('#valor') as HTMLInputElement;
        this.negociacoesView.update(this.negociacoes);
    }

e elas funcionavam normalmente, como na máquina do professor, pois tive que adicionar isso no tsconfig.json:

{
    "compilerOptions": {
        "outDir": "app/dist/js",
        "target": "ES6",
        "noEmitOnError": true,
        "noImplicitAny": true,
        "removeComments": true,
        "strictNullChecks": true,
        "experimentalDecorators": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true
    },
    "include": ["app/src/**/*"]
}

Em específico, essa linhas que não estão no código do professor:

        "strict": true,
        "forceConsistentCasingInFileNames": true

removia esse erro e alert que aparecia em meu terminal desde o começo do módulo 3 do curso de typeScript:

The compiler option "strict" should be enabled to reduce type errors. Ln 2, Col 6
The compiler option "forceConsistentCasingInFileNames" should be enabled to reduce issues when working with different OSes. Ln 2, Col 6

Enfim, o problema está que ao implementar o @domInjector e remover a declaraçao das variáveis no constructor. Aparece esse erro no terminal:

A propriedade 'inputData' não tem nenhum inicializador e não está definitivamente atribuída no construtor. Ln 12, Col 13
A propriedade 'inputQuantidade' não tem nenhum inicializador e não está definitivamente atribuída no construtor. Ln 14, Col 13
A propriedade 'inputValor' não tem nenhum inicializador e não está definitivamente atribuída no construtor. Ln 16, Col 13

Esse erro some, se eu remover as configurações iniciais que tive que implementar no tsconfig.json. Em contrapartida aqueles erros do começo do curso voltam a ser exibidos no terminal. Configurações iniciais mensionadas:

        "strict": true,
        "forceConsistentCasingInFileNames": true

Estás configurações iniciais que comentei não existem no código do professor. Eu estou iniciando por agora, e não tenho a experiência e os conhecimentos necessários para lidar com este tipo de problema.

Quero deixar claro, que o código sem estas configurações iniciais, continuam rodando como o do professor. A questão é que em meu terminal consta que há estes dois problemas.

1 resposta

E aí, Matheus! Beleza?

Então, quando a gente usa decoradores no TypeScript, tipo o @domInjector que você usou, o TypeScript quer que a gente inicialize essas propriedades. Se tirar a inicialização, ele reclama porque não sabe se a prop foi definida.

Pra dar um jeito nisso, é só garantir que as propriedades decoradas com @domInjector sejam inicializadas no construtor. Tipo, no construtor, você pega os elementos do DOM e joga nas propriedades certas.

Dá uma olhada no que você pode fazer no construtor da classe NegociacaoController:

// Código da classe NegociacaoController
// ... (mesmo código que você mostrou)

A ideia é inicializar as propriedades no construtor e deixar o @domInjector cuidar dos detalhes.

Você falou que colocou "strict": true e "forceConsistentCasingInFileNames": true no tsconfig.json e isso gerou uns perrengues, né? Se isso não tá batendo com o que você viu no curso, tira essas configurações por enquanto. Dá uma limpada no tsconfig.json assim:

{
    "compilerOptions": {
        "outDir": "app/dist/js",
        "target": "ES6",
        "noEmitOnError": true,
        "noImplicitAny": true
        // Tira essas duas linhas abaixo se estiverem dando ruim:
        // "strict": true,
        // "forceConsistentCasingInFileNames": true
    },
    "include": ["app/src/**/*"]
}

Pra Fechar

Usar decoradores no TypeScript é massa, só precisa de atenção nos detalhes, tipo inicializar as propriedades certinho. Espero que agora tenha clareado as ideias e ajudado a resolver essa parada. Segue o fluxo nos estudos aí!

Firmeza? Bons estudos e qualquer coisa, tamo junto!