0

I want to eagerly load a related aws-amplify gen 2 model and pass it on, but it seems to cause a typescript error no matter what I try. How do I do this without causing a typescript error? For background, I've done JavaScript, Python and dabbled in others but I'm new to TypeScript and Amplify. I'm using the web/ChatGPT to figure it out but neither seemed to help with this question.

The Error

Types of property 'dataType' are incompatible.
        Type '{ name: string; isComplex: boolean; dataCategories: LazyLoader<{ name: string; addDefault: boolean; dataEntries: LazyLoader<{ category: LazyLoader<... | null, false>; dataCategoryId: string; ... 7 more ...; readonly updatedAt: string; } | null, true>; ... 9 more ...; readonly updatedAt: string; } | null, true>; note...' is not assignable to type 'LazyLoader<{ name: string; isComplex: boolean; dataCategories: LazyLoader<{ name: string; addDefault: boolean; dataEntries: LazyLoader<{ category: LazyLoader<... | null, false>; dataCategoryId: string; ... 7 more ...; readonly updatedAt: string; } | null, true>; ... 9 more ...; readonly updatedAt: string; } | null, ...'.
          Type 'undefined' is not assignable to type 'LazyLoader<{ name: string; isComplex: boolean; dataCategories: LazyLoader<{ name: string; addDefault: boolean; dataEntries: LazyLoader<{ category: LazyLoader<... | null, false>; dataCategoryId: string; ... 7 more ...; readonly updatedAt: string; } | null, true>; ... 9 more ...; readonly updatedAt: string; } | null, ...'.

The Set Up

api.ts

/**
 * Subscribe to real-time updates for data categories, including their data types.
 * @param {Function} callback - Function to update state with new data.
 * @returns {Function} Unsubscribe function.
 */
export function subscribeToDataCategories(
  callback: (items: Schema["DataCategory"]["type"][]) => void
): () => void {
  const sub = client.models.DataCategory.observeQuery().subscribe({
    next: async (result: { items?: Schema["DataCategory"]["type"][] }) => {
      console.log("Updating DataCategories:", result.items);

      if (!result.items) {
        callback([]);
        return;
      }

      const enrichedItems = await Promise.all(
        result.items.map(async (item) => {
          try {
            let dataType: Schema["DataType"]["type"] | undefined;

            if (item.dataType && typeof item.dataType === "function") {
              // Resolve LazyLoader
              const resolved = await item.dataType();
              dataType = resolved?.data ?? undefined;
            }

            return { ...item, dataType };
          } catch (error) {
            console.error(
              `Failed to fetch DataType for ID ${item.dataTypeId}:`,
              error
            );
            return { ...item };
          }
        })
      );

      console.log("Enriched Categories:", enrichedItems);

      callback(enrichedItems);
    },
    error: (error: unknown) => {
      console.error("Subscription error:", error);
    },
  });

  return () => sub.unsubscribe(); // Cleanup function
}

Here is my resources.ts file

import { type ClientSchema, a, defineData } from "@aws-amplify/backend";
import { postConfirmation } from "../auth/post-confirmation/resource";

const schema = a
  .schema({
    UserProfile: a
      .model({
        email: a.string().required(),
        profileOwner: a.string(),
      })
      .secondaryIndexes((index) => [index("email")])
      .authorization((allow) => [
        allow.owner(),
        allow.ownerDefinedIn("profileOwner"),
        allow.groups(["Admins"]).to(["read"]),
      ]),
    DataType: a
      .model({
        name: a.string().required(),
        note: a.string(),
        isComplex: a.boolean().required(),
        dataCategories: a.hasMany("DataCategory", "dataTypeId"),
      })
      .secondaryIndexes((index) => [index("name")])
      .authorization((allow) => [allow.authenticated(), allow.publicApiKey()]),
    DataCategory: a
      .model({
        name: a.string().required(),
        note: a.string(),
        addDefault: a.boolean().required(),
        defaultValue: a.string(),
        options: a.string().array(), // For future use with options of values
        dataEntries: a.hasMany("DataEntry", "dataCategoryId"),
        dataTypeId: a.id().required(), // ✅ Explicitly define the reference field
        dataType: a.belongsTo("DataType", "dataTypeId"),
        entryCount: a.integer().default(0),
      })
      .secondaryIndexes((index) => [index("name")])
      .authorization((allow) => [
        allow.owner(),
        allow.groups(["Admins"]).to(["read"]),
        allow.publicApiKey(), // TODO: Remove. FOR TESTING
      ]),
    DataEntry: a
      .model({
        note: a.string(),
        category: a.belongsTo("DataCategory", "dataCategoryId"),
        dataCategoryId: a.id().required(),
        date: a.date().required(),
        value: a.string().required(),
        dummy: a.integer().default(0),
      })
      .secondaryIndexes((index) => [
        index("dataCategoryId")
          .name("categoryEntriesByDate")
          .queryField("listCategoryEntries")
          .sortKeys(["date"]),
        index("dummy")
          .name("entriesByDate")
          .queryField("listByDate")
          .sortKeys(["date"]),
      ])
      // client.models.DataEntry.listDataentryByDataCategoryId({dataCategoryId: "ID"})
      .authorization((allow) => [
        allow.owner(),
        allow.groups(["Admins"]).to(["read"]),
        allow.publicApiKey(), // TODO: Remove. FOR TESTING
      ]),
  })
  .authorization((allow) => [allow.resource(postConfirmation)]);

export type Schema = ClientSchema<typeof schema>;

// export const schema = schema;
export { schema };

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: "userPool", // Changed from public api key. https://docs.amplify.aws/react/build-a-backend/data/customize-authz/
    apiKeyAuthorizationMode: {
      expiresInDays: 30,
    },
  },
});

Attempts

Attempt 1

This time I tried partially custom types, still errored.

type ResolvedDataType = Omit<Schema["DataType"]["type"], "dataCategories"> & {
  dataCategories?: Schema["DataCategory"]["type"][];
};

type EnrichedDataCategory = Omit<Schema["DataCategory"]["type"], "dataType"> & {
  dataType?: ResolvedDataType;
};

export function subscribeToDataCategories(
  callback: (items: EnrichedDataCategory[]) => void
): () => void {

Attempt 2

Here I tried just adding DataType to the standard DataCategory type but it also errored.

export function subscribeToDataCategories(
  callback: (
    items: (Schema["DataCategory"]["type"] & {
      dataType?: Schema["DataType"]["type"];
    })[]
  ) => void
): () => void {

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.