Switch to infinite scroll (Full book)

Derived types

keyof: derive a type union from the keys of an object type

We make a type union out of the keys of an object type (defined with interface or type)

keys of an object type can be strings, numbers and symbols. The output type is keyof Foo:

interface Foo {
    id: string
    name: string
    weight: number
}

type KeyOfFoo = keyof Foo
const s: KeyOfFoo = "id" // keyof Foo

type T = keyof Foo & string // "id" | "name" | "weight"

We can remove non-string keys from the type by adding & string, though this is not needed if the type is known to declare only string keys. When we do it, we end up with a string literal type union instead.

derive a type from a type map

In this example, we build a type map, mapping strings (the keys) to their type.

We make a function that works with a specific key of the map ( <K extends KeyOfFoo>), that identifies which key K is used, and that infers the associated type through the use of Foo[K].

In this example, the function makes use of the derived type as a type argument, to improve the precision of the function it calls:

/* 1.0 the type map */
interface DocTypes {
    bedtimeEvents: BedtimeEvent
    proteinEvents: ProteinEvent
    // ...
}

/* 2.0 keyof type union */
type CollectionName = keyof DocTypes

/* 3.0 a function that identifies the key and derives the type */
function f<K extends CollectionName>(colName: K) {
    return colRef<DocTypes[K]>(colName) // DocTypes[K] is used as a type argument
    // DocTypes[K] resolves to the actual type depending on the string
}

const colRef = f("bedtimeEvents") // CollectionReference<BedtimeEvent>
const colRef = f("proteinEvents") // CollectionReference<ProteinEvent>
earlymorning logo

Derived types

keyof: derive a type union from the keys of an object type

We make a type union out of the keys of an object type (defined with interface or type)

keys of an object type can be strings, numbers and symbols. The output type is keyof Foo:

interface Foo {
    id: string
    name: string
    weight: number
}

type KeyOfFoo = keyof Foo
const s: KeyOfFoo = "id" // keyof Foo

type T = keyof Foo & string // "id" | "name" | "weight"

We can remove non-string keys from the type by adding & string, though this is not needed if the type is known to declare only string keys. When we do it, we end up with a string literal type union instead.

derive a type from a type map

In this example, we build a type map, mapping strings (the keys) to their type.

We make a function that works with a specific key of the map ( <K extends KeyOfFoo>), that identifies which key K is used, and that infers the associated type through the use of Foo[K].

In this example, the function makes use of the derived type as a type argument, to improve the precision of the function it calls:

/* 1.0 the type map */
interface DocTypes {
    bedtimeEvents: BedtimeEvent
    proteinEvents: ProteinEvent
    // ...
}

/* 2.0 keyof type union */
type CollectionName = keyof DocTypes

/* 3.0 a function that identifies the key and derives the type */
function f<K extends CollectionName>(colName: K) {
    return colRef<DocTypes[K]>(colName) // DocTypes[K] is used as a type argument
    // DocTypes[K] resolves to the actual type depending on the string
}

const colRef = f("bedtimeEvents") // CollectionReference<BedtimeEvent>
const colRef = f("proteinEvents") // CollectionReference<ProteinEvent>