Aloha.zone.io

Aloha's technical notes.

View on GitHub

Something tricky in TypeScript

Interfaces with excess properties

TypeScript lets us pass { size: number; label: string; } to something that only expected a { label: string; }, since TS has a structural subtyping system. But inline literal objects does not.

It is caused by excess properties check,

Play with the sample

Classes (nominal typing)

Also caused by structural typing. If class A and class B share the same members, the functions which require an instance of A, also accepts B as legal parameter.

Try the sample

Discriminated Unions

TypeScript has a feature called discriminated unions. Quoting from the docs, there are 2 requirements for discriminated unions:

It means in case:

interface Dog {
    kind: "dog"
    bark: string
}

interface Cat {
    kind: "cat"
    meow: string
}

type Animal = Cat | Dog

The type Animal is expected have property kind on it.

However, it does not work if the common property is a nested object, like:

interface Dog {
    taxonomy: {
        species: "Canis familiaris"
    }
    bark: string
}

interface Cat {
    taxonomy: {
        species: "Felis catus"
    }
    meow: string
}

Play with the sample

References

TypeScript’s quirks: How inconsistencies make the language more complex