Skip to content

Instantly share code, notes, and snippets.

@denisos
Last active June 7, 2026 19:29
Show Gist options
  • Select an option

  • Save denisos/b068303ff4e6fc9fe02526ad490db914 to your computer and use it in GitHub Desktop.

Select an option

Save denisos/b068303ff4e6fc9fe02526ad490db914 to your computer and use it in GitHub Desktop.
Typescript examples of useful basic language features
// typeof
// extract a type from runtime code, typeof "make a type of it" (i.e. from it)
// e.g. typeof "Hello world" => string
// only legal on variable names
// can be used with functions or any other expressions
// aside: typeof vs keyof: keyof takes a type and creates a string/number union of it's keys. So keyof creates a new type from a type ....whereas typeof creates a type from an expression. good post
// Given a function below type the function into MyFunc. When the function changes, the types change!
const myFunc = (name: string) => {
return `hello ${name}`;
};
type MyFunc = typeof myFunc;
// type a function return type (using built in ReturnType)
type MyFuncReturn = ReturnType<typeof myFunc>; // string
// Parameters
// You can also type the parameters using utility type Parameters
// Parameters is useful to extract type info from code you don't control e.g. external libraries
// but Parameters will return a tuple (array), so you could index result like so: MyFuncParams[0]. i.e. can use indexes on tuple types
type MyFuncParams = Parameters<typeof myFunc>; // string
// Promises
// The return type of an async function is a promise (which wraps the result returned), so use the global Promise type when typing it
// Awaited utility type is a way to unwrap Promises to get the returned type e.g. from async functions
// Create a union type from keys of an object
// using keyof and typeof together can give us the type we want, which updates automatically when the object changes
// in this example myKeyedObject instance is converted to a type and then we use keyof to access the keys
const myKeyedObject = { name: "denis", age: 40 };
type MyKeyedObjectKeys = keyof typeof myKeyedObject;
MyKeyedObjectKeys // "name" | "age"
// here's a case where we get all the values of the keys of an object using indexed access keyof as a shortcut
type Obj = typeof myKeyedObject;
type MyKeyedObjectKeyTypes = Obj[keyof Obj]
MyKeyedObjectKeyTypes // "string" | "number"
// note if we had added "as const" to end of myKeyedObject then the last line ^ would have returned literals "denis" | "40" (instead of "string" | "number" )
// here's a cool helper to get values as types using a ValueOf generic
type ValueOf<T> = T[keyof T];
const myObj = {
start: "startedit",
created: "createdit",
paid: "paidit"
} as const;
type MyObjType = typeof myObj
type ObjValue = ValueOf<MyObjType>; // "startedit" | "createdit" | "paidit"
type ObjKey = keyof MyObjType; // "start" | "created" | "paid"
// ...the ValueOf is same as: type ObjValue = MyObjType[keyof MyObjType]
// Discriminating union
// A union of types where each type in the union has a common field which is the "discriminator" to allow tell them apart
// e.g. state where status could be one of "loading" | "success" | "error" (just an example)
// within an if or switch (to narrow down) typescript will know which exact type you're using
// Extract (utility type)
// extract from a union
type LoadingEvent = Extract<Event, { status: "loading"} >;
// if any in union extend the 2nd param, then extract it. could end up with a union if more than one match
type Fruit = "apple" | "banana" | "orange"
type BananaAndOrange = Extract<Fruit, "banana" | "orange">
// if you just want to get the union type of a discriminated union then this will work:
type StatusType = Event["status"]; // "loading" | "success" | "error"
// ...this will also work for any common property in the types
// Exclude (utility type)
// extract from a union all which don't match e.g. all but success
type LoadingEvent = Exclude<Event, { status: "success"} >;
Indexed Access Types (on objects or arrays)
access one or more properties on a type using indexed access type, ts docs
e.g.
type Person = { age: number; name: string; alive: boolean, addr: { st: number } } };
type Age = Person["age"];
type I1 = Person["age" | "name"]
type I2 = Person[keyof Person];
you can go deep into a nested object to get a type
type Z3 = Person['addr']['st']
also works indexing on an array!
you can also convert an object to a type using typeof and then index to get types and create a union like this:
type PE = typeof programModeEnumMap;
export type IndividualProgram = PE["ONE_ON_ONE"] | PE['SELF_DIRECTED'] |
PE['PLANNED_ONE_ON_ONE'];
OR...pass a union to the type and get back a union
export type IndividualProgram = typeof programModeEnumMap[
| "ONE_ON_ONE"
| "SELF_DIRECTED"
| "PLANNED_ONE_ON_ONE"
| "PLANNED_SELF_DIRECTED"
]
you can also index into arrays, e.g.
const fruits = ["apple", "banana", "orange"] as const;
type AppleOrBanana = typeof fruits[0 | 1];
type Fruit = typeof fruits[number];
as const
convert entire object (or array) to type literals, in code below you can't write req.method = "POST"
works with object nesting (unlike Object.freeze which only works on 1st level)
as const freezes values as literal types and also adds a readonly annotation
literal unions make use of this e.g. type Status = "loading" | "error";
you can combine with non-literal types
const req = {
url: "https://example.com",
method: "GET" }
as const;
template literals
its like regex for types!
you could define a type check to ensure that routes must start with a "/" e.g. "/", "/users" etc
type Route = `/${string}`
create type for those routes which have substitution param
type Routes = "/users" | "/users/:id" | "/posts" | "/posts/:id";
type DynamicRoutes = Extract<Routes, `${string}:${string}`>;
// "/users/:id" | "/posts/:id"
union of strings of all permutations (this is wild)
type BreadType = "rye" | "brown" | "white";
type Filling = "cheese" | "ham" | "salami";
type Sandwich = `${BreadType} sandwich with ${Filling}`;
// "rye sandwich with cheese" | "rye sandwich with ham" | etc
using ts-toolbelt to split and join type literals
import { S } from "ts-toolbelt";
type Path = "Users/John/Documents/notes.txt";
type SplitPath = S.Split<Path, '/'>; // ["Users", "John", "Documents", "notes.txt"]
type BackAgain = S.Join<SplitPath, ':'> // "Users:John:Documents:notes.txt"
turn string literals into object with names as keys
type TemplateLiteralKey = `${"user" | "post" | "comment"}${"Id" | "Name"}`;
type ObjectOfKeys = Record<TemplateLiteralKey, string>; // { userId: string, userName: string...}
type UprObjectOfKeys = Record<Uppercase<Event>, string>; // uppercase
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment