@tslint: Type trivally inferred from a literal

Dear TypeScript...

My thoughts on this directive about no-inferrable-types has made me realize something: it doesn't serve me and I'm going to show why:


export class TransactionsListComponent {
    addOnBlur = true;
    readonly separatorKeysCodes = [ENTER, COMMA] as const;
    #transactions: Transactions;
    @Input() get transactions(): Transactions {
        return this.#transactions;
    }
    set transactions(value: Transactions) {
        this.#transactions = value;
        this.refresh();
    }
    @Output() transactionsChange = new EventEmitter<Transactions>();
    @Input() showFilters: boolean;
    @Input() filters: TransactionFilter;
    @Output() filtersChange = new EventEmitter<TransactionFilter>();
    @Input() showPaginate: boolean;
    @Input() txShow?: TransactionShowHeaders;
    @Input() editable: boolean;
    @Input() showHeader: boolean;
    @Input() showTags: boolean;
    currentlyEditing: EditPlaceholder;
    txns: Transactions;
    accountId2name: AccountIdHashMap;
    #oldTxnLen: number;
    constructor(protected accountsService: AccountsService) {
        console.log('new TransactionsListComponent()');
        this.showFilters = true;
        this.filters = <TransactionFilter>{
            fromDate: new Date(Date.now() - DEFAULT_DATERANGE),
            toDate: new Date(),
            description: '',
            budgets: [],
            accounts: [],
            tags: [],
            limit: -1,
            sort: {
                column: 'datePosted',
                asc: true
            },
            page: {
                pageIndex: 0,
                pageSize: 0,
                length: 0,
            }
        };
        this.showPaginate = true;
        this.showHeader = true;
        this.showTags = true;
        this.editable = false;
        this.currentlyEditing = <EditPlaceholder>{
            datePending: false,
            datePosted: false,
            amount: false,
            description: false,
            merchant: false,
            transactionType: false,
            tags: false,
        };
        this.#transactions = new Transactions();
        this.txns = new Transactions();
        this.accountId2name = {};
        this.#oldTxnLen = 0;
    }
}

With this directive in place, it makes me put the initialization in the constructor, thus doubling my efforts at describing my code and making it many more lines to write. What I contend with is my OCD telling me that everything must be consistent with my code across all classes so the formatting is generally easier on the eyes. However, this just does not serve. To place the trivally typed

Without the directive in place, here's how that class would look like:


export class TransactionsListComponent {
    addOnBlur = true;
    readonly separatorKeysCodes = [ENTER, COMMA] as const;
    #transactions = new Transactions();
    @Input() get transactions(): Transactions {
        return this.#transactions;
    }
    set transactions(value: Transactions) {
        this.#transactions = value;
    }
    @Output() transactionsChange = new EventEmitter<Transactions>();
    @Output() budgets = new EventEmitter<Budgets>();
    @Input() showFilters = true;
    @Input() filters = EMPTY_TRANSACTION_FILTER;
    @Output() filtersChange = new EventEmitter<TransactionFilter>();
    @Input() showPaginate = true;
    @Input() truncate = false;
    txShow: TransactionShowHeaders = Settings.fromLocalStorage().txShow;
    @Input() editable = false;

    txns = new Transactions();
    accountId2name = <Id2NameHashMap>{};
    page: PageEvent = {pageIndex: 0, pageSize: 10, length: 0};
    sort: TxnSortHeader = {column: 'datePosted', asc: true};
    length = 0;

    #oldTxnLen = 0;
    #cachedUpdates?: Subscription;
    #postFilterTxns = new Transactions();

    constructor(protected accountsService: AccountsService) {
        this.transactionsChange.subscribe(() => this.postFilter());
        this.filtersChange.subscribe(() => this.postFilter());
    }
}

Now the constructor is much smaller and the properties all are iniialized upon definition in the same line rather than again in the constructor. Okay, so it may make some types obvious if it's a primitive, but I've seen stuff like const sub = observable.subscribe(); complain about cannot determine the type sub even though it can tell me the return type of the function. That just baffles me...

Anyways, if you see this in previous versions of my code, you'll know why. This denotes a change in my pattern of writing code. I ended up turning this option off. How is this done? Update tslint.json as such:


{
    "rules": {
        "@typescript-eslint/no-inferrable-types": "off"
    }
}

Make sure you have at least this data structure present somewhere in your tslint.json (or in angular's case, possibly .eslintrc.json) and it won't complain if you want to type-annotate and initiazlize without the type-police barking about cluttered code.

Happy Typescripting!

Comments

Popular posts from this blog

Setup and Install Monero(d) -- p2pool -- xmrig

Build xmrig on Linux

Perl Net::SSH2::SFTP Example