• Build an enum-like value set from a plain key → value map, together with the helpers needed to use it: the value array, a runtime type guard, and a table of localization keys. This is the foundation almost every SoHL constant set is declared with, so understanding it explains the shape of ACTOR_KIND, ITEM_KIND, VALUE_DELTA_OPERATOR, and the rest.

    The typical pattern is to immediately destructure the result, giving the map, its values, its guard, and its labels each a conventional name, and then to derive the value-union type with (typeof KIND)[keyof typeof KIND]:

    Type Parameters

    • const T extends Record<string, unknown>

      The literal key → value map; inferred from def.

    Parameters

    • prefix: string

      Localization-key prefix joined to each entry key with a . to form DefinedType.labels (e.g. "TYPES.Actor").

    • def: T

      The key → value map defining the set.

    Returns {
        choices: Record<KindValue & string, string>;
        isValue: (value: unknown) => value is KindValue;
        kind: T;
        labels: Record<StringKeys, string>;
        Type: KindValue;
        values: KindValue[];
    }

    A DefinedType bundle: { kind, values, isValue, labels, Type }.

    export const {
    kind: ACTOR_KIND, // { BEING: "being", COHORT: "cohort", ... }
    values: ActorKinds, // ["being", "cohort", ...]
    isValue: isActorKind, // (v) => v is "being" | "cohort" | ...
    labels: actorKindLabels, // { BEING: "TYPES.Actor.BEING", ... }
    } = defineType("TYPES.Actor", {
    BEING: "being",
    COHORT: "cohort",
    STRUCTURE: "structure",
    VEHICLE: "vehicle",
    });

    // The value-union type, named from the kind map:
    export type ActorKind = (typeof ACTOR_KIND)[keyof typeof ACTOR_KIND];
    // => "being" | "cohort" | "structure" | "vehicle"

    isActorKind("being"); // true
    isActorKind("dragon"); // false
    actorKindLabels.BEING; // "TYPES.Actor.BEING" (feed to the localizer)
    • The const type parameter preserves the literal keys and values, so the value union is exact (not widened to string).
    • labels produces localization keys, not display text — resolve them through SohlLocalize when rendering.
    • The returned Type member is a compile-time-only phantom; prefer the (typeof KIND)[keyof typeof KIND] form shown above for naming the union.