@sprs/ts-hkt
v0.0.2
Published
Higher-kinded types for TypeScript
Downloads
5
Readme
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:
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:
function Concat (str1: string, str2: string): string {
return `${str1}${str2}`;
}Apply type parameters with apply to obtain a new type:
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:
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:
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:
thispolymorphism in interfaces - the concrete type ofthisdoesn't resolve fully until a property is accessed- Intersection collapse of
unknown & TtoT
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:
// 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]