Recent articles About

Compiling enterprise

Ivan Koshelev blog on software development

Articles for tags 'template literal types' Pragmatic uses of Typescript type system 04 Domain Modeling with Typescript [2021 November 22] Typescript, types, domain modeling, literal types, tagged union types, template literal types

This article gives an overlook of Typescript features that let us provide safety guarantees for our code unlike any other mainstream language. Typescript is a somewhat paradoxical language. It is a superset of Javascript and Javascript has one of the simplest, least strict typing systems among mainstream languages, where even distinction between int and float or char and string are deemed excessive. Javascript is also dynamically typed, a trait that may seem down-right harmful to developers coming from Java or C# background. And yet, Typescript, sitting on top of JS type system, allows us to model types far more strictly than any other mainstream language.

Article is quite big, owning to almost 4 years of complex Domain Modeling experience in Typescript that I'm attempting to sum-up and considerable amount of ways in which Typescript language features can be applied to Domain Modeling. First part of this article explains Typescript features that we will use and is most useful to developers coming from other languages. If you are up to speed with TS, you can jump to the second part, which covers their application.

continue reading
Pragmatic uses of Typescript type system 03 Tag hierarchies via Template Literal Types [2021 May 09] Typescript, types, tagged union types, template literal types, hierarchy, polymorphism Features described in the articles require Typescript 4.3, which is in beta at the time of writing.

Tagged union types are a great part of Typescript, indispensible when working with groups of related data types, the kind we are likely to receive in JSON form from some API. They allow us to generalize groups of those types and strong-type functions that can operate on any member of the group.


const catTag = `cat` as const;
const dogTag = `dog` as const;

type CatRecord = {
    type: typeof catTag,
    name: string,
    huntsMice: boolean,
}

type DogRecord = {
    type: typeof dogTag,
    name: string,
    lovesFetch: boolean
}

type AnimalRecord = CatRecord | DogRecord;

declare const cat: CatRecord
let a: AnimalRecord = cat; // all good :-)
TS playground

This approach works fine in many situations, but its limits quickly become visible when we try modeling hierarchies of data.


const vanTag = `van` as const;
const ambulanceTag = `ambulance` as const;
type FuelType = 'gasoline' | 'diesel' | 'electric';

type VanRecord = {
    type: typeof vanTag,
    fuelType: FuelType
}

type AmbulanceRecord = Omit<VanRecord, 'type'> & {
    type: typeof ambulanceTag,
    medicalEquipment: string[]
}

type FuelStation = {
    availableFuels: FuelType[]
}

function canRefuel(station: FuelStation, van: VanRecord) {
    return station.availableFuels.some(x => x === van.fuelType);
}

declare const station: FuelStation;
declare const van: VanRecord;
declare const ambulance: AmbulanceRecord;

canRefuel(station, van); // fine
canRefuel(station, ambulance); // error!
TS playground

So how can we both have tagged types and make sure that 'canRefuel' function accepts any type derived from 'Van'?

continue reading
Ivan Koshelev photo

I'm passionate for anything that can be programed and automated to make life better for all of us.

Archives

  1. November 2021 (1)
  2. May 2021 (1)
  3. March 2020 (1)
  4. August 2019 (1)
  5. July 2019 (1)
  6. May 2019 (1)
  7. February 2019 (1)
  8. October 2017 (1)
  9. August 2017 (3)
  10. July 2017 (3)
  11. May 2017 (3)

Elsewhere

  1. GitHub@IKoshelev
  2. NuGet@IKoshelev
  3. LinkedIn