Ts.Kind
Higher-kinded type utilities for TypeScript.
Provides type-level functions and utilities for simulating higher-kinded types in TypeScript, enabling more advanced type-level programming patterns.
Import
import { Ts } from '@wollybeard/kit'
// Access via namespace
Ts.Kindimport { Kind } from '@wollybeard/kit/ts'Constants
[C] PrivateKindReturn
typeof PrivateKindReturnPrivate symbol for storing kind return type.
[C] PrivateKindParameters
typeof PrivateKindParametersPrivate symbol for storing kind parameters.
Types
[T] Apply
type Apply<$Kind, $Args> =
// @ts-expect-error - Intentional type manipulation for kind simulation
($Kind & { parameters: $Args })['return']Higher-kinded type utilities for TypeScript.
Provides type-level functions and utilities for simulating higher-kinded types in TypeScript, enabling more advanced type-level programming patterns.
[I] Kind
interface Kind<$Params = unknown, $Return = unknown> {
parameters: $Params
return: $Return
}Define a kind (higher-kinded type) function interface.
Provides a standard structure for defining type-level functions that can be applied using the Apply utility.
$Params
- The parameter types this kind accepts
$Return
- The return type this kind produces
Examples:
interface BoxOf extends Kind<[unknown], Box<any>> {
return: Box<this['parameters'][0]>
}[T] Parameters
type Parameters<$Kind> = $Kind extends Kind<infer P, any> ? P : neverExtract the parameter types from a kind.
$Kind
- The kind to extract parameters from
[T] Return
type Return<$Kind> = $Kind extends Kind<any, infer R> ? R : neverExtract the return type from a kind.
$Kind
- The kind to extract return type from
[I] Identity
interface Identity extends Kind {
// @ts-expect-error
return: this['parameters'][0]
}Create a type-level identity function.
Returns the input type unchanged. Useful as a default or placeholder in kind compositions.
Examples:
type Same = Kind.Apply<Kind.Identity, [string]> // string[I] Const
interface Const<$Const> extends Kind {
return: $Const
}Create a type-level constant function.
Always returns the same type regardless of input.
$Const
- The constant type to always return
Examples:
type AlwaysString = Kind.Apply<Kind.Const<string>, [number]> // string[T] PrivateKindReturn
type PrivateKindReturn = typeof PrivateKindReturn[T] PrivateKindParameters
type PrivateKindParameters = typeof PrivateKindParameters[I] Private
interface Private {
[PrivateKindReturn]: unknown
[PrivateKindParameters]: unknown
}Private kind interface using symbols instead of string keys.
This provides a more secure way to define higher-kinded types as the symbols cannot be accessed outside the module.
Examples:
interface BoxKind extends PrivateKind {
// @ts-expect-error
[PRIVATE_KIND_RETURN]: Box<this[PRIVATE_KIND_PARAMETERS][0]>
[PRIVATE_KIND_PARAMETERS]: unknown
}[T] PrivateApply
type PrivateApply<$Kind extends Private, $Args> =
($Kind & { [PrivateKindParameters]: $Args })[PrivateKindReturn]Apply arguments to a private kind.
$Kind
- The private kind to apply
$Args
- The arguments to apply
Examples:
type BoxOfString = PrivateKindApply<BoxKind, [string]> // Box<string>[T] MaybePrivateApplyOr
type MaybePrivateApplyOr<$MaybeKind, $Args, $Or> = $MaybeKind extends Private
? PrivateApply<$MaybeKind, $Args>
: $Or[T] IsPrivateKind
type IsPrivateKind<T> = T extends Private ? true : falseCheck if a type is a private kind.
T
- The type to check
Examples:
type Test1 = IsPrivateKind<BoxKind> // true
type Test2 = IsPrivateKind<string> // false[T] Pipe
type Pipe<$Kinds extends readonly Kind[], $Input> = $Kinds extends readonly [
infer __first__ extends Kind,
...infer __rest__ extends readonly Kind[],
] ? Pipe<__rest__, Apply<__first__, [$Input]>>
: $InputApply a tuple of Kinds sequentially (left-to-right composition).
Takes an array of Kind functions and applies them in sequence from left to right. This enables composing multiple type-level transformations without creating specialized intermediate types.
Application order: Left-to-right (first Kind, then second, then third, etc.)
$Kinds
- Tuple of Kind functions to apply sequentially
$Input
- The initial type to transform
Examples:
// Define some extractors
interface Awaited extends Kind {
return: Awaited<this['parameters'][0]>
}
interface ArrayElement extends Kind {
return: this['parameters'][0] extends (infer El)[] ? El : never
}
// Compose them: Promise<string[]> -> string[] -> string
type Result = Pipe<[Awaited, ArrayElement], Promise<string[]>>
// Result: string
// Compose three: () => Promise<number[]> -> Promise<number[]> -> number[] -> number
type Result2 = Pipe<
[ReturnType, Awaited, ArrayElement],
() => Promise<number[]>
>
// Result2: number