Skip to main content

schema.Union

Describe a schema which is a union of multiple schemas. This is useful if you need the polymorphic behavior provided by schema.Array or schema.Values but for non-collection fields.

  • definition: required An object mapping the definition of the nested entities found within the input array
  • schemaAttribute: required The attribute on each entity found that defines what schema, per the definition mapping, to use when normalizing. Can be a string or a function. If given a function, accepts the following arguments:
    • value: The input value of the entity.
    • parent: The parent object of the input array.
    • key: The key at which the input array appears on the parent object.

Instance Methods

  • define(definition): When used, the definition passed in will be merged with the original definition passed to the Union constructor. This method tends to be useful for creating circular references in schema.
Naming

Union is named after the set theory concept just like TypeScript Unions

Usage

note

If your data returns an object that you did not provide a mapping for, the original object will be returned in the result and an entity will not be created.

Fixtures
GET /feed
[{"id":1,"type":"link","url":"https://ntucker.true.io","title":"Nate site"},{"id":10,"type":"post","content":"good day!"}]
api/Feed.ts
abstract class FeedItem extends Entity {
  readonly id: number = 0;
  declare readonly type: 'link' | 'post';
  pk() {
    return `${this.id}`;
  }
}
class Link extends FeedItem {
  readonly type = 'link' as const;
  readonly url: string = '';
  readonly title: string = '';
}
class Post extends FeedItem {
  readonly type = 'post' as const;
  readonly content: string = '';
}

const feed = new RestEndpoint({
  path: '/feed',
  schema: [
    new schema.Union(
      {
        link: Link,
        post: Post,
      },
      'type',
    ),
  ],
});
FeedList.tsx
function FeedList() {
  const feedItems = useSuspense(feed);
  return (
    <div>
      {feedItems.map(item =>
        item.type === 'link' ? (
          <LinkItem link={item} key={item.pk()} />
        ) : (
          <PostItem post={item} key={item.pk()} />
        ),
      )}
    </div>
  );
}
function LinkItem({ link }: { link: Link }) {
  return <a href={link.url}>{link.title}</a>;
}
function PostItem({ post }: { post: Post }) {
  return <div>{post.content}</div>;
}
render(<FeedList />);
🔴 Live Preview
Store

Github Events

Contribution activity comes from grouping github events by their type. Each type of Event has its own distinct schema, which is why we use schema.Union

More Demos