Monthly Archives: April 2023

Override private methods in TypeScript

First things first: a word of caution – do this only if you absolutely have to. TypeScript has these checks for a reason, and probably in 99% of the cases you should respect and abide these restrictions. But if your scenario falls within the 1% where you must in a subclass override a private method of a superclass – this post shows a way to do this.

Let’s say we have a class that defines a generic starship, and what happens to it when it’s hit by a weapon:

type Hit = 'phaser' | 'antimatter spread' | 'photon torpedo'

class Starship {
    private totalDamage: number;

    constructor(private shipName: string) {
        this.totalDamage = 0;
    }

    private addDamage(damage: number) {
        this.totalDamage += damage;
    }

    public isHitBy(hit: Hit) {
        console.log(`${this.shipName} is hit by ${hit}!`)

        switch(hit) {
            case 'phaser':
                this.addDamage(100);
                break;
            case 'antimatter spread':
                this.addDamage(300);
                break;
            case 'photon torpedo':
                this.addDamage(500);
                break
        }
    }
}

You can create your own class of starship based on this generic class, then build a ship of the new class, and simulate it being hit by a weapon:

class Galaxy extends Starship {
    constructor(name: string) {
        super(name);
    }
}

const enterprise = new Galaxy('Enterprise');
enterprise.isHitBy('photon torpedo');

Output:

"Enterprise is hit by photon torpedo!"

This is fine, but as you’ve seen the base class has a secret feature to calculate damage inflicted by the weapon. It is secret, because it’s defined by a private method, and is not exposed to derived classes. But, like Kirk in Kobayashi Maru, you want to break the rules, and have this forbidden knowledge. Continue reading →

Reverse values into variables in tmplr

tmplr is a versatile templating tool that lets you quickly create a repository from a template customized for your needs. By running a recipe it can substitute placeholder variables with your own values making the repository truly your own. For example it can update package.json with dynamic values from git context. It can do much more, put for the purpose of this post we will concentrate on literal values in code files.

Let’s say you have a JavaScript code that performs some AWS SDK/CDK actions, and it requires AWS account IDs – for dev and prod deployment. In a regular repo you would define config.js something like this:

const awsAccounts = {
   dev: '1234567890',
   prod: '0987654321'
}

But if we’re building a template repo – we don’t want to hardcode those values. Instead we could use tmplr placeholder variables:

const awsAccounts = {
   dev: '{{ tmplr.dev_account_id }}',
   prod: '{{ tmplr.prod_account_id }}'
}

Save this file as config.tmplr.js – it becomes our template. A user of your template then can create a tmplr recipe:

steps:
  - read: dev_account_id
    eval: '1234567890'
  - read: prod_account_id
    eval: '0987654321'
  - copy: config.tmplr.js
    to: config.js

then save this it into .tmplr.yml file into repo root, and run tmplr cli command – it will create config.js file from config.tmplr.js substituting variables for values from the recipe.

It works great, but there is a problem. Continue reading →