Skip to content

Latest commit

 

History

History
56 lines (42 loc) · 1.91 KB

custom-kinds.md

File metadata and controls

56 lines (42 loc) · 1.91 KB



A higher-kinded-type companion to ts-toolbelt


[Guide]: Custom Kinds

If the API does not provide a feature, defining a custom Kind in your application logic is somewhat straight-forward. As an example, let's define a Kind that takes in an object and omits all non-string values.

The approach is usually to define the type first using a generic, and then 'wrap' it in a kind construction.

type OmitNonStrings<O extends Record<string, unknown>> = {
  [key in keyof O as O[key] extends string ? key : never]: O[key];
};

type Result = OmitNonStrings<{ foo: number; bar: string }>; // { bar: string }

After OmitNonStrings is available, we can wrap it in a kind as follows:

import { Kind } from "hkt-toolbelt";

declare abstract class OmitNonStringsKind extends Kind {
  abstract f: (
    x: Cast<this[Kind._], Record<string, unknown>>
  ) => OmitNonStrings<typeof x>;
}

The Cast parameter enforces that this kind must be applied with a subtype of Record<string, unknown>. This is a useful pattern for ensuring that the kind is applied correctly.

Now that OmitNonStringsKind is available, we can use it in kind combinators like List.Map to map over a tuple of object types.