Closest thing to structs / dataclasses / records in typescript with default values

Data-only classes are easy to understand; you can add ‘methods’ (functions taking them) to them when you import them; there is no worries of using this wrong and it’s usually easier to figure out if they are modified (partly because you can make a function argument const a bit more easily than with this); you know that they have a fixed set of attributes; methods and data are easily distinguishable. There’s a reason structs fundamental in golang and something like structs has been added or always existed in python, swift, scala, etc.

So how do we do it in typescript? One mediocre option is to use regular classes and restrain yourself to avoid methods. I won’t go into detail on that or other mediocre options that require repeating yourself three times. Below is a pretty good option, and now my go-to for structs in typescript.

Use a function to make your struct and ReturnType for the exported type.

export function newCar(args: {
    year?: number
    make?: string
    model: string
    owner: [string, string]
}) {
    const defaults = {
        year: 1999,
        make: "toyota",
    }
    return { ...defaults, ...args }
    // to get a Readonly<Car>:
    // return Object.freeze(args)
}

export type Car = ReturnType<typeof newCar>

const c = newCar({ model: "corolla", owner: ["Gorg", "Blafson"] })

export function print(c: Car) {
    console.log(`${c.owner}'s gorgeous ${c.year} ${c.model} from ${c.make}`)
}

Ezpz. This also shows you how to do default/optional destructured parameters with thorough type hinting.

Posted by Luke.

Blog App Twitter