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

Cannot type dto model - TS2589: Type instantiation is excessively deep and possibly infinite.

Open WojciechKasprzyk opened this issue 5 months ago • 0 comments

Before opening, please confirm:

JavaScript Framework

Angular

Amplify APIs

GraphQL API

Amplify Version

v6

Amplify Categories

api

Backend

Amplify CLI

Environment information

  System:
    OS: macOS 14.6.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 73.05 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.2.0 - /usr/local/bin/node
    npm: 10.7.0 - /usr/local/bin/npm
    bun: 1.0.0 - ~/.bun/bin/bun
  Browsers:
    Chrome: 127.0.6533.122
    Safari: 17.6
    Safari Technology Preview: 18.0
  npmPackages:
    @angular-devkit/build-angular: ^18.2.1 => 18.2.1 
    @angular/animations: ^18.2.1 => 18.2.1 
    @angular/cli: ^18.2.1 => 18.2.1 
    @angular/common: ^18.2.1 => 18.2.1 
    @angular/compiler: ^18.2.1 => 18.2.1 
    @angular/compiler-cli: ^18.2.1 => 18.2.1 
    @angular/core: ^18.2.1 => 18.2.1 
    @angular/forms: ^18.2.1 => 18.2.1 
    @angular/platform-browser: ^18.2.1 => 18.2.1 
    @angular/platform-browser-dynamic: ^18.2.1 => 18.2.1 
    @angular/router: ^18.2.1 => 18.2.1 
    @aws-amplify/backend: ^1.1.1 => 1.1.1 
    @aws-amplify/backend-cli: ^1.2.5 => 1.2.5 
    @aws-amplify/ui-angular: ^5.0.19 => 5.0.19 
    @ngrx/effects: ^18.0.2 => 18.0.2 
    @ngrx/entity: ^18.0.2 => 18.0.2 
    @ngrx/eslint-plugin: ^18.0.2 => 18.0.2 
    @ngrx/operators: ^18.0.2 => 18.0.2 (18.0.1)
    @ngrx/schematics: ^18.0.2 => 18.0.2 
    @ngrx/store: ^18.0.2 => 18.0.2 
    @ngrx/store-devtools: ^18.0.2 => 18.0.2 
    @types/jasmine: ~5.1.4 => 5.1.4 
    aws-amplify: ^6.5.2 => 6.5.2 
    aws-amplify/adapter-core:  undefined ()
    aws-amplify/analytics:  undefined ()
    aws-amplify/analytics/kinesis:  undefined ()
    aws-amplify/analytics/kinesis-firehose:  undefined ()
    aws-amplify/analytics/personalize:  undefined ()
    aws-amplify/analytics/pinpoint:  undefined ()
    aws-amplify/api:  undefined ()
    aws-amplify/api/server:  undefined ()
    aws-amplify/auth:  undefined ()
    aws-amplify/auth/cognito:  undefined ()
    aws-amplify/auth/cognito/server:  undefined ()
    aws-amplify/auth/enable-oauth-listener:  undefined ()
    aws-amplify/auth/server:  undefined ()
    aws-amplify/data:  undefined ()
    aws-amplify/data/server:  undefined ()
    aws-amplify/datastore:  undefined ()
    aws-amplify/in-app-messaging:  undefined ()
    aws-amplify/in-app-messaging/pinpoint:  undefined ()
    aws-amplify/push-notifications:  undefined ()
    aws-amplify/push-notifications/pinpoint:  undefined ()
    aws-amplify/storage:  undefined ()
    aws-amplify/storage/s3:  undefined ()
    aws-amplify/storage/s3/server:  undefined ()
    aws-amplify/storage/server:  undefined ()
    aws-amplify/utils:  undefined ()
    jasmine-core: ~5.2.0 => 5.2.0 (4.6.1)
    karma: ~6.4.4 => 6.4.4 
    karma-chrome-launcher: ~3.2.0 => 3.2.0 
    karma-coverage: ~2.2.1 => 2.2.1 
    karma-coverage-coffee-example:  1.0.0 
    karma-jasmine: ~5.1.0 => 5.1.0 
    karma-jasmine-html-reporter: ~2.1.0 => 2.1.0 
    rxjs: ~7.8.1 => 7.8.1 
    rxjs/ajax:  undefined ()
    rxjs/fetch:  undefined ()
    rxjs/operators:  undefined ()
    rxjs/testing:  undefined ()
    rxjs/webSocket:  undefined ()
    tslib: ^2.7.0 => 2.7.0 (2.6.3, 2.0.3, 2.4.1, 2.2.0, 2.3.1, 1.14.1)
    typescript: ~5.5.4 => 5.5.4 (4.4.4, 4.9.5)
    zone.js: ~0.14.10 => 0.14.10 
  npmGlobalPackages:
    @angular/cli: 16.1.6
    @aws-amplify/cli: 12.12.4
    @ionic/cli: 7.2.0
    cordova-res: 0.15.4
    cordova: 12.0.0
    corepack: 0.28.1
    jest: 29.7.0
    n: 9.2.3
    npm: 10.7.0
    ts-node: 10.9.2

Describe the bug

My project uses an external backend, which I fetch to retrieve a schema. I want to present the part of the schema:

const schema = a.schema({
  CmsPage: a
    .model({
      id: a.id().required(),
      gci: a.id().required(),
      channelID: a.id().required(),
      name: a.string().required(),
      createdBy: a.id(),
      slug: a.string(),
      title: a.string(),
      content: a.string(),
      metaDescription: a.string(),
      metaKeywords: a.string(),
      isActive: a.boolean(),
      isDefault: a.boolean(),
      isPublic: a.boolean()
    })
    .identifier(['id', 'gci', 'channelID'])
    .secondaryIndexes((index) => [
      index("gci").queryField("listCmsPagesByGci"),
      index("channelID").queryField("listCmsPagesByChannel").sortKeys(["gci"]),
    ])
    .authorization((allow) => [allow.publicApiKey()]),

  CmsMenu: a
    .model({
      id: a.id().required(),
      gci: a.id().required(),
      channelID: a.id().required(),
      symbol: a.string().required(),
      items: a.json(),
      hidOnSitemap: a.boolean(),
      createdBy: a.id(),
      languageKey: a.string(),
      description: a.string(),
      isActive: a.boolean(),
      isPublic: a.boolean()
    })
    .identifier(['id', 'gci', 'channelID'])
    .secondaryIndexes((index) => [
      index("gci").queryField("listCmsMenusByGci"),
      index("channelID").queryField("listCmsMenusByChannel").sortKeys(["gci"]),
    ])
    .authorization((allow) => [allow.publicApiKey()]),

})

Then I want to get the type of models and there are two problems:

  1. If there none of the model fields is a type of JSON I can get the page type
import api from "@/api";

export type PageDto = Awaited<ReturnType<typeof api.models.CmsPage.list>>;

export type PageItemsDto = PageDto['data'];
export type PageItemDto = PageItemsDto['0'];

But the way I get it is quite brutal. Is there any other way to get the schema model type?

  1. If there any of the model fields is a type of JSON (like CmsMenu of my example) I cannot do anything because TS thinks that it's possibly looped
import api from "@/api";

export type MenuDto = Awaited<ReturnType<typeof api.models.CmsMenu.list>>;  //ERROR: TS2589: Type instantiation is excessively deep and possibly infinite.

export type MenuItemsDto = MenuDto['data'];
export type MenuItemDto = MenuItemsDto['0'];
image

Expected behavior

I expect either:

  1. DTO Interface that I can import
  2. json() field type that does not break with error TS2589
  3. Any other way to type a model

Reproduction steps

npm install git submodule update --init --recursive npx ampx generate outputs --branch master --app-id {{backendId}}

Code Snippet

// Put your code below this line.

Log output

// Put your logs below this line


aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

WojciechKasprzyk avatar Aug 27 '24 12:08 WojciechKasprzyk