@sprs/ts-hkt
v0.0.2
Published
Higher-kinded types for TypeScript
Downloads
3
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:
this
polymorphism in interfaces - the concrete type ofthis
doesn't resolve fully until a property is accessed- Intersection collapse of
unknown & T
toT
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]