edgedb-js icon indicating copy to clipboard operation
edgedb-js copied to clipboard

TypeScript reports that an overloaded property from extended type does not exist

Open nathanburgess opened this issue 11 months ago • 0 comments

Discord thread: https://discord.com/channels/841451783728529451/1300525436165423266

  • EdgeDB Version: 5.6+adb9e77
  • EdgeDB CLI Version: EdgeDB CLI 5.5.1+cc9315a
  • OS Version: Sequoia 15.0

Seeing an issue where TypeScript is reporting a property as not existing where it clearly exists.

Steps to Reproduce:

  1. Create an abstract type
  2. Create another type that uses the abstract type
  3. Create another type that extends the type from step 2 and overload a property from the abstract type in step 1
  4. Attempt to use this property in a query using the TS client

TypeScript error:

error TS2345: Argument of type '{ date: datetime_currentλFuncExpr; name: "Started"; entity: $expr_Select<{ __element__: ObjectType<"Phase", { __type__: LinkDesc<$ObjectType, Cardinality.One, ... 4 more ..., false>; ... 54 more ...; "<phases": LinkDesc<...>; }, Omit<...>, ExclusiveTuple>; __cardinality__: Cardinality.AtMostOne; }>; rela...' is not assignable to parameter of type '{ [x: @${string}]: TypeSet<BaseType, Cardinality> | scalarLiterals; id?: string | TypeSet<$uuid, Cardinality.AtMostOne | Cardinality.One | Cardinality.Empty> | undefined; ... 7 more ...; date: Date | TypeSet<...>; }'.
  Object literal may only specify known properties, and 'name' does not exist in type '{ [x: @${string}]: TypeSet<BaseType, Cardinality> | scalarLiterals; id?: string | TypeSet<$uuid, Cardinality.AtMostOne | Cardinality.One | Cardinality.Empty> | undefined; ... 7 more ...; date: Date | TypeSet<...>; }'.

Schema:

abstract type EventBase {
  required name: str;
  multi link tags: EventTag;
}

type Event extending EventBase {
  required date: datetime;
}

type StartedEvent extending Event {
  overloaded required name: str {
    default := <str>EventNames.Started;
  };
}

Code with the error:

const completePhase = e.params(
  {
    id: e.uuid,
  },
  (params) => {
    const phase = e.select(e.Phase, (p) => ({
      filter_single: e.op(p.id, "=", params.id),
    }));

    return e.insert(e.StartedEvent, {
      date: e.datetime_current(),
      name: e.EventNames.Started, // This is the problem line
      entity: phase,
      related: phase.project,
    });
  },
);

The generated types:

export type $StartedEventλShape = $.typeutil.flatten<$EventλShape & {
  "name": $.PropertyDesc<_std.$str, $.Cardinality.One, false, false, false, true>;
}>;

export type $EventBaseλShape = $.typeutil.flatten<$WithUserTimestampsλShape & {
  "tags": $.LinkDesc<$EventTag, $.Cardinality.Many, {}, false, false,  false, false>;
  "name": $.PropertyDesc<_std.$str, $.Cardinality.One, false, false, false, false>;
}>;

nathanburgess avatar Oct 29 '24 14:10 nathanburgess