Hyperlinkv0.8.0-beta.28

Store

Store.extendconstsrc/Store.ts:783
<const Shapes extends StoreShapes>(shapes: Shapes): <
  const Base extends StoreContractValue
>(
  base: Base
) => StoreContractValue<Base["shapes"] & Shapes, Base["custom"]>
<const Custom extends Readonly<Record<string, unknown>>>(
  methods: (shapes: ShapeHandles<StoreShapes>) => Custom
): <const Base extends StoreContractValue>(
  base: Base
) => StoreContractValue<Base["shapes"], Base["custom"] & Custom>
<
  const Shapes extends StoreShapes,
  const Custom extends Readonly<Record<string, unknown>>
>(
  shapes: Shapes,
  methods: (shapes: ShapeHandles<Shapes>) => Custom
): <const Base extends StoreContractValue>(
  base: Base
) => StoreContractValue<Base["shapes"] & Shapes, Base["custom"] & Custom>
<const Shapes extends StoreShapes, const Base extends StoreContractValue>(
  shapes: Shapes,
  base: Base
): StoreContractValue<Base["shapes"] & Shapes, Base["custom"]>
<
  const Base extends StoreContractValue,
  const Custom extends Readonly<Record<string, unknown>>
>(
  methods: (shapes: ShapeHandles<Base["shapes"]>) => Custom,
  base: Base
): StoreContractValue<Base["shapes"], Base["custom"] & Custom>
<
  const Shapes extends StoreShapes,
  const Base extends StoreContractValue,
  const Custom extends Readonly<Record<string, unknown>>
>(
  shapes: Shapes,
  methods: (shapes: ShapeHandles<Base["shapes"] & Shapes>) => Custom,
  base: Base
): StoreContractValue<Base["shapes"] & Shapes, Base["custom"] & Custom>

Extend an existing contract with more shapes, more custom methods, or both — the composable counterpart to contract (which builds one from scratch).

Concrete-preservation guarantee. When a methods builder is supplied together with its base (the data-first forms extend(methods, base) and extend(shapes, methods, base)), the builder's return Custom is inferred at its exact type and merged as Base["custom"] & Custom. Each method therefore keeps its precise signature all the way onto effects — e.g. completed: (entry, success, elapsed) => Effect<void, StoreWriteError, Storage>, never a widened Record<string, unknown>. The methods builder receives the base's shape handles (ShapeHandles over Base["shapes"], plus any newly declared shapes), so event.append / event.read are typed for the base's own row schemas.

The pipeable / data-last forms (extend(methods) and extend(shapes, methods)) still preserve the builder's return Custom concretely, but — because the base is not yet known when the builder is written — its shape handles are typed generically (the newly declared shapes only, for extend(shapes, methods)). Prefer the data-first forms when methods must read base shapes.

constructorscontracteffectsShapeHandles
Source src/Store.ts:78362 lines
export const extend: {
  <const Shapes extends StoreShapes>(
    shapes: Shapes,
  ): <const Base extends StoreContractValue>(
    base: Base,
  ) => StoreContractValue<Base["shapes"] & Shapes, Base["custom"]>;
  <const Custom extends Readonly<Record<string, unknown>>>(
    methods: (shapes: ShapeHandles<StoreShapes>) => Custom,
  ): <const Base extends StoreContractValue>(
    base: Base,
  ) => StoreContractValue<Base["shapes"], Base["custom"] & Custom>;
  <
    const Shapes extends StoreShapes,
    const Custom extends Readonly<Record<string, unknown>>,
  >(
    shapes: Shapes,
    methods: (shapes: ShapeHandles<Shapes>) => Custom,
  ): <const Base extends StoreContractValue>(
    base: Base,
  ) => StoreContractValue<Base["shapes"] & Shapes, Base["custom"] & Custom>;
  <const Shapes extends StoreShapes, const Base extends StoreContractValue>(
    shapes: Shapes,
    base: Base,
  ): StoreContractValue<Base["shapes"] & Shapes, Base["custom"]>;
  <
    const Base extends StoreContractValue,
    const Custom extends Readonly<Record<string, unknown>>,
  >(
    methods: (shapes: ShapeHandles<Base["shapes"]>) => Custom,
    base: Base,
  ): StoreContractValue<Base["shapes"], Base["custom"] & Custom>;
  <
    const Shapes extends StoreShapes,
    const Base extends StoreContractValue,
    const Custom extends Readonly<Record<string, unknown>>,
  >(
    shapes: Shapes,
    methods: (shapes: ShapeHandles<Base["shapes"] & Shapes>) => Custom,
    base: Base,
  ): StoreContractValue<Base["shapes"] & Shapes, Base["custom"] & Custom>;
} = ((first: unknown, second?: unknown, third?: unknown) => {
  if (isMethodsFn(first) && second === undefined) {
    return <const Base extends StoreContractValue>(base: Base) => extendCore(base, undefined, first);
  }
  if (isShapeRecord(first) && isMethodsFn(second) && third === undefined) {
    return <const Base extends StoreContractValue>(base: Base) =>
      extendCore(base, first, second as StoreMethodsFn<Base["shapes"] & typeof first>);
  }
  if (isShapeRecord(first) && second === undefined) {
    return <const Base extends StoreContractValue>(base: Base) => extendCore(base, first);
  }
  if (isMethodsFn(first) && isStoreContractValue(second)) {
    return extendCore(second, undefined, first);
  }
  if (isShapeRecord(first) && isMethodsFn(second) && isStoreContractValue(third)) {
    return extendCore(third, first, second);
  }
  if (isShapeRecord(first) && isStoreContractValue(second)) {
    return extendCore(second, first);
  }
  throw new Error("Store.extend: invalid arguments");
}) as never;