Polymorphism
A relationship can lead to nodes of several classes, told apart by their labels. Declare an abstract fragment and its subclasses. A subclass carries its own labels and its superclass’s:
@NodeFragment({ labels: ['WebUser'] })export abstract class WebUser { @NodeId() uuid: string; displayName: string;}
@NodeFragment({ labels: ['Anonymous'] })export class AnonymousWebUser extends WebUser { // stored as (:WebUser:Anonymous) anonymousToken: string;}
@NodeFragment({ labels: ['Registered'] })export class RegisteredWebUser extends WebUser { // stored as (:WebUser:Registered) email: string;}
@GraphView()export class GuideUserWithPolymorphicWebUser { @Root() core: GuideUser; @GraphRelationship({ type: 'IS_WEB_USER', target: () => WebUser }) webUser?: WebUser;}A node loads as the subclass its labels say, so instanceof tells them apart:
for (const guide of await gom.loadAll(GuideUserWithPolymorphicWebUser)) { if (guide.webUser instanceof AnonymousWebUser) { console.log(guide.webUser.anonymousToken); }}A subclass is known once its module has been loaded, so import every subclass before the first load. A save writes the labels of the object’s own class.
Filtering by subclass. Either declare a view over the subclass, which loads only the roots related to one:
@GraphView()export class AnonymousGuideUser { @Root() core: GuideUser; @GraphRelationship({ type: 'IS_WEB_USER', target: () => AnonymousWebUser, required: true }) webUser: AnonymousWebUser;}or keep the polymorphic view and filter at query time:
await gom.loadAll(GuideUserWithPolymorphicWebUser, (q) => ({ where: q.webUser.instanceOf(AnonymousWebUser) }));await gom.loadAll(GuideUserWithPolymorphicWebUser, (q) => ({ where: anyOf(q.webUser.instanceOf(AnonymousWebUser), q.webUser.instanceOf(RegisteredWebUser))}));Required Relationships
Section titled “Required Relationships”TypeScript erases ?:, so a view says which relationships it requires:
| Declaration | Loads |
|---|---|
@GraphRelationship({ type: 'IS_WEB_USER' }) webUser?: WebUser |
every root; webUser is undefined where there is none |
@GraphRelationship({ type: 'IS_WEB_USER', required: true }) webUser: WebUser |
only the roots that have one |
@GraphRelationship({ type: 'IS_WEB_USER', target: () => WebUser }) webUsers: WebUser[] |
every root; [] where there are none |

