Higher kinded types are not currently possible in typescript but let us start by explaining why they exist.
In functional programming there is the concept of a functor. A functor is simply something that can be mapped over. In OOP speak, we’d call it a mappable or some sort of container such as
Array that contains a
1 2 3 4
The above example is mapping over an Array and it is mapping from an array of
int to an array of
bool. In this example, the
Array is the functor. The functor keeps its shape meaning the same number of elements exist after the mapping operation but each element could potentially change.
A functor can be thought of as a container with a
map function. A functor is mapping between categories, meaning that it can map from type
a to type
b. The functor in the above example is the array and the type
a would be int with type
b the bool.
In haskell, functor has the following type signature:
You can think of
fmap as functor map.
If we consider the type signature for
What might not be obvious is that
b from the above are actually type parameters. Any lowercase type in haskell is a type parameter.
The more specialised
Functor instance for lists looks like this:
The existing list
map function is used for the
map has the following signture:
If we now start filling in the type parameters for functor, then the
f type parameter is the type constructor
The functor mapping function
(a, b) -> f a -> f b defines the mapping of a functor of type
a to a functor of type
b. Another way to think of this is an
b or in this case a list of
a or a list of
The more specialised version of
fmap for list looks like this:
Hopefully it is clear that
f is the container or
list in this specific instance that maps a list of
a to a list of
In the above example
f is the higher kinded type and both
b are both type parameters.
A higher kinded type (HKT) is simply a type parameter that takes a type parameter. The equivolence with higher order function HOF is that an HOF can take a function as an argument.
In haskell, there are types and there are kinds. You have concreate types like
String. All of these are the kind
*. Why? Because they cannot take any type parameters.
[a] is a parameterised type because it takes one concrete type and has the form
* -> * and is called a first order type.
A higher kinded type abstracts the parameterised type
 and has the form
(* -> *) -> *.
f is of kind
(* -> *) -> * and
b are of kind
* which is often referred to as the ground type.
Where is the typescript?
Now when we try and define functor in typescript, we quickly come unstuck trying to define an
a to an
b because typescript does not support higher kinded types or type parameters that take type parameters.
1 2 3
A number of the functional typescript libraries like fp-ts have come up with a similar work around for the lack of higher kinded types.
They all have a similar interface:
1 2 3 4
HKT takes 2 type parameters
A. Thinking in terms of kinds,
F represents the first class parameterised type
(* -> *) and
_A represents the ground type
We can now define functor like this:
1 2 3
The above code is now equivalent to the haskell version, we have a
map function that maps over a container or box of
A and returns a container or box of
Hopefully higher kinded types will land in typescript soon but until then I think this is a very inventive solution to a difficult problem.