Hi there! Are you looking for the official Deno documentation? Try docs.deno.com for all your Deno learning needs.

Usage

import * as fun from "https://raw.githubusercontent.com/baetheus/fun/main/kind.ts";

Kind is a collection of types used for doing something called Type Substitution. The core idea here is that sometimes there is a function that is generic at two levels, at the concrete type as well as at the type leve. A simple example of this is a forEach function. In javascript the built in Array and Set data structures both have a built in forEach method. If we look at Array and Set we can see that the creation functions are similar.

  • const arr = new Array<number>() returns Array;
  • const set = new Set<number>() returns Set;

If we look at the type signitures on forEach for arr and set we also notice a similar pattern.

  • type A = (typeof arr)['forEach'] returns (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
  • type B = (typeof set)['forEach'] returns (callbackfn: (value: number, value2: number, set: Set<number>) => void, thisArg?: any) => void

Both forEach methods have the same concrete value of number but differ in that they operate over an Array or a Set. Here is a table to illustrate this pattern a bit more clearly.

Structure Outer Type Inner Type forEach Type
Array Array A (value: A, index: number, struct: A[]) => void
Set Set A (value: A, index: number, struct: Set) => void
Map<K, V> Map K (key), V (value) (value: V, key: K, struct: Map<K, V>) => void

In general we can see that the forEach function could have a more generic type signiture like this:

type ForEach<Outer> = {
  forEach: <K, V>(struct: Outer<K, V>) => (value: V, key: K, struct: Outer<K, V>) => void;
}

Unfortunately, while these types of patterns are abundant within TypeScript (and most programming languages). The ability to pass generic types around and fill type holes is not built into TypeScript. However, with some type magic we can create our own type level substitutions using methods pionered by gcanti in fp-ts.

§Interfaces

Fix

Fix a concrete type as a non-substituting Kind. This allows one to define algebraic structures over things like number, string, etc.

Hold

The Hold interface allows one to trick the typescript compiler into holding onto type information that it would otherwise discard. This is useful when creating an interface that merges multiple type classes (see Flatmappable).

Kind

Kind is an interface that can be extended to retrieve inner types using "this".

§Type Aliases

$

$ is an alias of Substitute, lifting out, in, and inout substitutions to positional type parameters.

AnySub

An extension type to be used to constrain in input to an outer container with any concrete types.

In

Access the Premappable substitution type at index N

InOut

Access the Invariant substitution type at index N

Intersect

A type level utility that turns a type union into a type intersection. This type is dangerous and can have unexpected results so extra runtime testing is necessary when used.

Nest

Some Flatmappable Transform kinds only have one out type, in those cases we use this Nest type to make the transform kind cleaner.

Out

Access the Covariant substitution type at index N

Spread

Spread the keys of a struct union into a single struct.

Substitute

Substitute is a substitution type, taking a Kind implementation T and substituting it with types passed in S.

Substitutions

The Substitutions type splits the different type level substitutions into tuples based on variance.