npm package: @sprs/ts-hkt
Description: Higher-kinded types for TypeScript
Author: Brett Mitchell
Latest version: 0.0.2


# Introduction

This library implements a form of higher-kindedness in TypeScript.

Disclaimer: Unless you already implement a more complex form of higher-kindedness, you are almost certain to inflate the complexity of your codebase by using this utility. Approach the question of adoption with caution and a healthy dose of skepticism.

## Usage

To use this library, import `tc` (shorter alias for `TypeConstructor`) from `@sprs/ts-hkt` and extend it, overriding at least the `result` property.

`tc` acts like a type-system-level function, with parameters and a return type. `tc` itself accepts two type parameters, one to constrain the input types (must be a tuple), and one to constrain the output type. (`tc <InputTypeConstraint, OutputTypeConstraint>`)

Overriding the `result` property on an interface extending from `tc` acts as the "body" of the type function.

Example type constructor, `Concat`:

```ts
import { tc } from '@sprs/ts-hkt';

interface Concat extends tc <[string, string], string> {
  result: `${this[0]}${this[1]}`
}
```

If you were to make up an analagous runtime function that is more-or-less equivalent to the above, it might look like this:

```ts
function Concat (str1: string, str2: string): string {
  return `${str1}${str2}`;
}
```

Apply type parameters with `apply` to obtain a new type:

```ts
import { apply } from '@sprs/ts-hkt';

// interface Concat ...

type GreetSusan = apply <Concat, ['Hola, ', 'Susan'];
// -> type GreetSusan: 'Hola, Susan';
```

Type constructors created with `tc` are automatically curried. Partially apply type parameters to obtain a new type function:

```ts
import { partial, apply } from '@sprs/ts-hkt';

// interface Concat ...

type Greet = partial <Concat, ['Hello, ']>;
type GreetJohn = apply <Greet, ['John']>;
// -> type GreetJohn: 'Hello, John';
```

Use `call` for isomorphic partial and full type function application:

```ts
import { call } from '@sprs/ts-hkt';

// interface Concat ...

type Greet = call <Concat, ['Hello, ']>;
type GreetJohn = call <Greet, ['John']>;
// -> type GreetJohn: 'Hello, John';
```

## Implementation

`@sprs/ts-hkt` simulates type functions using existing TS language features. The core idea is to express a type which depends on other types through a mechanism _other than_ type parameters.  

The specific language features used to simulate higher-kinded types are:
1. `this` polymorphism in interfaces - the concrete type of `this` doesn't resolve fully until a property is accessed
2. Intersection collapse of `unknown & T` to `T`

A minimal implementation of higher-kinded types stripped of the additional constraint and partial application features this library provides might look something like the following:

```typescript
// All type functions extend from this interface
interface TypeConstructor {
  params: unknown;
  result: unknown;
}

type apply <Fn extends TypeConstructor, Params> =
  (Fn & { params: Params })['result'];

// Specific instance of a type function
interface PairOf extends TypeConstructor {
  result: [this['params'], this['params']];
}

type PairOfNumber = apply <PairOf, number>;
// => [number, number]
```