API reference@evolu/commonLookup › Structural

type Structural<T> = T extends StructuralScalar
  ? T
  : T extends ReadonlyArray<infer Item>
    ? ReadonlyArray<Structural<Item>>
    : T extends StructuralFunction
      ? never
      : T extends object
        ? {
            readonly [
              K in keyof T as K extends symbol
                ? never
                : Extract<T[K], StructuralFunction> extends never
                  ? K
                  : never
            ]: Structural<Exclude<T[K], StructuralFunction>>;
          } & {
            readonly [
              K in keyof T as K extends symbol
                ? K
                : Extract<T[K], StructuralFunction> extends never
                  ? never
                  : K
            ]?: never;
          }
        : never;

Defined in: packages/common/src/Lookup.ts:300

Compile-time structural form of T for structural lookup APIs.

This exists because StructuralKey is the runtime serialization model, not a good public generic constraint for interface-shaped objects. StructuralKey models object values with a string index signature, which is stricter than ordinary interfaces like { readonly id: string } even though the runtime serializer accepts such plain objects.

Structural<T> checks a concrete type recursively at compile time instead: scalars pass through, arrays recurse, object properties recurse, and function-valued and symbol-keyed properties are rejected. Symbol-keyed properties are rejected because runtime serialization reads only enumerable string keys, so they would be silently ignored. This keeps public structural APIs ergonomic for interface-based inputs while preserving the same runtime constraints as structural lookup serialization.

See