hand sketched logo of electrons orbiting a nucleus

Types from Types

T ⇒ T

Personal notes expanding on everything you can already learn here: https://www.typescriptlang.org/docs/handbook/2/types-from-types.html

Introduction

Lets look two things that seeem a bit similar but are actually quite different.

GenFunc will be the type of a runtime function that takes in a generic paramerter.

TypeHelper will be the type of a non-runtime, typetime only function that takes a type and returns a type. (No one really calls it typetime, but this will only run in the type server while editing and building.)

type GenFunc = <T>(arg: T) => T; // runtime function

type TypeHelper<T> = T; // typetime function

In this post will only care about exploring what we can do with TypeHelper.

Below when I mention things like array, object, etc. I mean the type of those things.

keyof

This allows us to move from (object) => union.

type Person = {
  name: string;
  age: number;
};

type UnionOfKeys<T> = keyof T;

type PersonKeys = UnionOfKeys<Person>; // 'name' | 'age'

typeof

This allows us to move from runtime into typetime!

const person = {
  name: 'Bob',
  age: 42,
};

// YES
type Person = typeof person; // { name: string; age: number; }

// NOPE: since T is "coming from" <T>, it is already a type!
type RuntimeToType<T> = typeof T;

Indexed Access

This allows us to get some piece of a type.

If we have an object and index on a key, then we get back the value.

type Person = {
  name: string;
  age: number;
};

type Name = Person['name']; // string

If we have an object and index on a union of keys, then we get back a union of values.

type Person = {
  name: string;
  age: number;
};

type NameOrAge = Person['name' | 'age']; // string | number

If we have a array and index on a number instance, then we get back one member.

type People = {
  name: string;
  age: number;
}[];

type FirstPerson = People[0]; // { name: string; age: number; }

If we have an array and index on number type, then we get back the union of the members.

type SomeNums = [1, 2, 3];

type SomeNumsUnion = SomeNums[number]; // 1 | 2 | 3

We can also combine the use of keyof and indexed access to get a union of all the values of an object.

type Person = {
  name: string;
  age: number;
};

type PersonValues = Person[keyof Person]; // string | number

Conditional Types

This adds a new keyword of extends...

Mapped Types

tk...

Template Literal Types

tk...