prisma-nestjs-graphql icon indicating copy to clipboard operation
prisma-nestjs-graphql copied to clipboard

XXXUpdateWithoutYYY is not assignable to Prisma.XXXUpdateWithoutYYY

Open TMInnovations opened this issue 4 years ago • 20 comments

First, thank you for that awesome library! I love it!

Second: For some Entities I see "Problems" in the VSCode Problems-Panel. I'm glad it compiles without errors, but.. did anyone else have similar problems like I do (see beneath)? I

I can try to set up a minimal reproducable example next week if the problem isn't clear enough from the error description beneath. Please let me know if the effort is worth it ;-)

{
	"resource": "/c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/src/models/parcel/parcel.service.ts",
	"owner": "typescript",
	"code": "2322",
	"severity": 8,
	"message": "Type 'ParcelUpdateInput' is not assignable to type '(Without<ParcelUpdateInput, ParcelUncheckedUpdateInput> & ParcelUncheckedUpdateInput) | (Without<...> & ParcelUpdateInput)'.\n  Type 'ParcelUpdateInput' is not assignable to type 'Without<ParcelUncheckedUpdateInput, ParcelUpdateInput> & ParcelUpdateInput'.\n    Type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/@prisma/client/nestjs-graphql/index\").ParcelUpdateInput' is not assignable to type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/.prisma/client/index\").Prisma.ParcelUpdateInput'.\n      The types of 'labels.upsert' are incompatible between these types.\n        Type 'DalabelUpsertWithWhereUniqueWithoutParcelInput[]' is not assignable to type 'Enumerable<DalabelUpsertWithWhereUniqueWithoutParcelInput>'.\n          Type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/@prisma/client/nestjs-graphql/index\").DalabelUpsertWithWhereUniqueWithoutParcelInput[]' is not assignable to type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/.prisma/client/index\").Prisma.DalabelUpsertWithWhereUniqueWithoutParcelInput[]'.\n            Type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/@prisma/client/nestjs-graphql/index\").DalabelUpsertWithWhereUniqueWithoutParcelInput' is not assignable to type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/.prisma/client/index\").Prisma.DalabelUpsertWithWhereUniqueWithoutParcelInput'.\n              Types of property 'update' are incompatible.\n                Type 'DalabelUpdateWithoutParcelInput' is not assignable to type '(Without<DalabelUpdateWithoutParcelInput, DalabelUncheckedUpdateWithoutParcelInput> & DalabelUncheckedUpdateWithoutParcelInput) | (Without<...> & DalabelUpdateWithoutParcelInput)'.\n                  Type 'DalabelUpdateWithoutParcelInput' is not assignable to type 'Without<DalabelUncheckedUpdateWithoutParcelInput, DalabelUpdateWithoutParcelInput> & DalabelUpdateWithoutParcelInput'.\n                    Type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/@prisma/client/nestjs-graphql/index\").DalabelUpdateWithoutParcelInput' is not assignable to type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/.prisma/client/index\").Prisma.DalabelUpdateWithoutParcelInput'.\n                      The types of 'scan_dalabel_scans.upsert' are incompatible between these types.\n                        Type 'ScanUpsertWithWhereUniqueWithoutDalabelInput[]' is not assignable to type 'Enumerable<ScanUpsertWithWhereUniqueWithoutDalabelInput>'.\n                          Type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/@prisma/client/nestjs-graphql/index\").ScanUpsertWithWhereUniqueWithoutDalabelInput[]' is not assignable to type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/.prisma/client/index\").Prisma.ScanUpsertWithWhereUniqueWithoutDalabelInput[]'.\n                            Type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/@prisma/client/nestjs-graphql/index\").ScanUpsertWithWhereUniqueWithoutDalabelInput' is not assignable to type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/.prisma/client/index\").Prisma.ScanUpsertWithWhereUniqueWithoutDalabelInput'.\n                              Types of property 'update' are incompatible.\n                                Type 'ScanUpdateWithoutDalabelInput' is not assignable to type '(Without<ScanUpdateWithoutDalabelInput, ScanUncheckedUpdateWithoutDalabelInput> & ScanUncheckedUpdateWithoutDalabelInput) | (Without<...> & ScanUpdateWithoutDalabelInput)'.\n                                  Type 'ScanUpdateWithoutDalabelInput' is not assignable to type 'Without<ScanUncheckedUpdateWithoutDalabelInput, ScanUpdateWithoutDalabelInput> & ScanUpdateWithoutDalabelInput'.\n                                    Type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/@prisma/client/nestjs-graphql/index\").ScanUpdateWithoutDalabelInput' is not assignable to type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/.prisma/client/index\").Prisma.ScanUpdateWithoutDalabelInput'.\n                                      The types of 'parcel.upsert.update' are incompatible between these types.\n                                        Type 'ParcelUpdateWithoutScansInput' is not assignable to type '(Without<ParcelUpdateWithoutScansInput, ParcelUncheckedUpdateWithoutScansInput> & ParcelUncheckedUpdateWithoutScansInput) | (Without<...> & ParcelUpdateWithoutScansInput)'.\n                                          Type 'ParcelUpdateWithoutScansInput' is not assignable to type 'Without<ParcelUncheckedUpdateWithoutScansInput, ParcelUpdateWithoutScansInput> & ParcelUpdateWithoutScansInput'.\n                                            Type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/@prisma/client/nestjs-graphql/index\").ParcelUpdateWithoutScansInput' is not assignable to type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/.prisma/client/index\").Prisma.ParcelUpdateWithoutScansInput'.\n                                              The types of 'delivery.upsert.update' are incompatible between these types.\n                                                Type 'DeliveryUpdateWithoutParcelInput' is not assignable to type '(Without<DeliveryUpdateWithoutParcelInput, DeliveryUncheckedUpdateWithoutParcelInput> & DeliveryUncheckedUpdateWithoutParcelInput) | (Without<...> & DeliveryUpdateWithoutParcelInput)'.\n                                                  Type 'DeliveryUpdateWithoutParcelInput' is not assignable to type 'Without<DeliveryUncheckedUpdateWithoutParcelInput, DeliveryUpdateWithoutParcelInput> & DeliveryUpdateWithoutParcelInput'.\n                                                    Type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/@prisma/client/nestjs-graphql/index\").DeliveryUpdateWithoutParcelInput' is not assignable to type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/.prisma/client/index\").Prisma.DeliveryUpdateWithoutParcelInput'.\n                                                      Types of property 'branch' are incompatible.\n                                                        Type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/@prisma/client/nestjs-graphql/index\").BranchUpdateOneWithoutDelivery_branch_deliveriesInput' is not assignable to type 'import(\"c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/.prisma/client/index\").Prisma.BranchUpdateOneWithoutDelivery_branch_deliveriesInput'.",
	"source": "ts",
	"startLineNumber": 29,
	"startColumn": 47,
	"endLineNumber": 29,
	"endColumn": 51,
	"relatedInformation": [
		{
			"startLineNumber": 16915,
			"startColumn": 5,
			"endLineNumber": 16915,
			"endColumn": 9,
			"message": "The expected type comes from property 'data' which is declared here on type '{ select?: ParcelSelect; include?: ParcelInclude; data: (Without<ParcelUpdateInput, ParcelUncheckedUpdateInput> & ParcelUncheckedUpdateInput) | (Without<...> & ParcelUpdateInput); where: ParcelWhereUniqueInput; }'",
			"resource": "/c:/Users/tm/TmiCloud/2_TMI/Projects/2021/01_DEAD_LAS2/02_Software/backend/node_modules/.prisma/client/index.d.ts"
		}
	]
}

BranchUpdateOneWithoutDelivery_branch_deliveriesInput from this library is:

export declare class BranchUpdateOneWithoutDelivery_branch_deliveriesInput {
    create?: InstanceType<typeof BranchCreateWithoutDelivery_branch_deliveriesInput>;
    connectOrCreate?: InstanceType<typeof BranchCreateOrConnectWithoutDelivery_branch_deliveriesInput>;
    upsert?: InstanceType<typeof BranchUpsertWithoutDelivery_branch_deliveriesInput>;
    connect?: InstanceType<typeof BranchWhereUniqueInput>;
    disconnect?: boolean;
    delete?: boolean;
    update?: InstanceType<typeof BranchUpdateWithoutDelivery_branch_deliveriesInput>;
}

BranchUpdateOneWithoutDelivery_branch_deliveriesInput from Prisma is:

  export type BranchUpdateOneWithoutDelivery_branch_deliveriesInput = {
    create?: XOR<BranchCreateWithoutDelivery_branch_deliveriesInput, BranchUncheckedCreateWithoutDelivery_branch_deliveriesInput>
    connectOrCreate?: BranchCreateOrConnectWithoutDelivery_branch_deliveriesInput
    upsert?: BranchUpsertWithoutDelivery_branch_deliveriesInput
    connect?: BranchWhereUniqueInput
    disconnect?: boolean
    delete?: boolean
    update?: XOR<BranchUpdateWithoutDelivery_branch_deliveriesInput, BranchUncheckedUpdateWithoutDelivery_branch_deliveriesInput>
  }

Part of the Prisma model is

generator nestjsgraphql {
  provider                              = "node node_modules/prisma-nestjs-graphql"
  fields_Validator_from                 = "class-validator"
  fields_Validator_input                = true
  requireSingleFieldsInWhereUniqueInput = true
  emitSingle                            = true
  emitCompiled                          = true
  purgeOutput                           = true
  output                                = "../node_modules/@prisma/client/nestjs-graphql"
}

model Parcel {
  id String @id @default(cuid())

  l Float?
  b Float?
  h Float?

  mass Float?


  // RELATIONS

  labels Dalabel[]

  delivery    Delivery? @relation(fields: [id_delivery], references: [id])
  id_delivery String?

  customer        Customer? @relation(fields: [customer_number], references: [number])
  customer_number String?

  surcharges Surcharge[]


  // INVERSE RELATIONS

  scans Scan[]

}

What I try and where I get the error is at:

import {ParcelUpdateInput} from '@prisma/client/nestjs-graphql';

update(where: ParcelWhereUniqueInput, updateParcelInput: ParcelUpdateInput) {
  return this.prisma.parcel.update({ where, data: updateParcelInput });
}

Thank you for taking time!

TMInnovations avatar Oct 27 '21 09:10 TMInnovations

Sorry, but I cannot reproduce the error with default settings.

model Parcel {
  id String @id @default(cuid())

  l Float?
  b Float?
  h Float?

  mass Float?


  // RELATIONS

  labels Dalabel[]

  delivery    Delivery? @relation(fields: [id_delivery], references: [id])
  id_delivery String?

  customer        Customer? @relation(fields: [customer_number], references: [number])
  customer_number String?

  surcharges Surcharge[]


  // INVERSE RELATIONS

  scans Scan[]

}

model Scan {
  id       String  @id @default(cuid())
  Parcel   Parcel? @relation(fields: [parcelId], references: [id])
  parcelId String?
}

model Surcharge {
  id       String  @id @default(cuid())
  Parcel   Parcel? @relation(fields: [parcelId], references: [id])
  parcelId String?
}

model Delivery {
  id     String   @id @default(cuid())
  Parcel Parcel[]
}

model Customer {
  number String   @id @default(cuid())
  Parcel Parcel[]
}

model Dalabel {
  id       String  @id @default(cuid())
  Parcel   Parcel? @relation(fields: [parcelId], references: [id])
  parcelId String?
}

However, with requireSingleFieldsInWhereUniqueInput = true it gives

Property 'id' is missing in type '{}' but required in type 'ParcelWhereUniqueInput'

It break compatibility. I added note to documentation https://github.com/unlight/prisma-nestjs-graphql/blob/master/README.md#requiresinglefieldsinwhereuniqueinput

And I did not catch any errors related to data property:

import { ParcelUpdateInput } from '../../@generated';
import { ParcelWhereUniqueInput } from '../../@generated';

    const where: ParcelWhereUniqueInput = {};
    const updateParcelInput: ParcelUpdateInput = {};
    void $prisma.parcel.update({ where, data: updateParcelInput });

unlight avatar Oct 27 '21 17:10 unlight

Thank you for your answer. However, a strategy to overcome this problem is not very clear for me. Could you maybe explain the problem and a way to work around?

I had a free slot for creating a reproducible scenario. Please find it here: https://github.com/TMInnovations/prisma-nestjs-graphql-failing

It even breaks the application now. What needs to be changed to make the application work (or run at least ;-) )?

Edit: The behavior doesn't change with requireSingleFieldsInWhereUniqueInput in my case.

TMInnovations avatar Oct 28 '21 15:10 TMInnovations

I thought that problem is requireSingleFieldsInWhereUniqueInput, but it is not. I able to reproduce it from repository you provided, unfortunately, it is not clear where is the root of issue.

unlight avatar Oct 28 '21 20:10 unlight

Thank you for testing!

I really want to help with this issue as I'm using this library for several of my projects. Is there anything I can help you with to resolve this bug? Do you have any thoughts about why this bug might happen?

https://github.com/TMInnovations/prisma-nestjs-graphql-failing/tree/try-to-get-it-working-1 In a new branch I tried to resolve the issue by first removing all /// @HideField directives => didn't work In the same branch I moved further and marked all possible fields of the schema as optional (?) => didn't work In the same branch I moved backwards and marked all possible fields as required (removed ?) => didn't work

Finally I removed the Address model and its connection to other models => building and running but the red lines and Errors in the "Problem" Section of VS-Code remain.

In another branch I will try to remove other models and evaluate if it fails or works. Any better idea how to tackle the issue? Help is very appreciated!

TMInnovations avatar Oct 29 '21 06:10 TMInnovations

It also builds when removing Country model. Still red lines and entries in Problem Section of VSCode https://github.com/TMInnovations/prisma-nestjs-graphql-failing/tree/try-to-get-it-working-2

TMInnovations avatar Oct 29 '21 06:10 TMInnovations

Removed all enums, didn't change anything, still failing https://github.com/TMInnovations/prisma-nestjs-graphql-failing/tree/try-to-get-it-working-3

TMInnovations avatar Oct 29 '21 06:10 TMInnovations

Also tried to move the output path of the prisma plugin => doesn't change anything

TMInnovations avatar Oct 29 '21 07:10 TMInnovations

I was able to narrow down schema models to

model Customer {
  number              String        @id
  destinations        Destination[]
  collectors          Profile[]     @relation(name: "collector")
  favoriteDelivery    Delivery      @relation(fields: [id_favoriteDelivery], references: [id])
  id_favoriteDelivery String        @unique
  profile             Profile       @relation(fields: [id_profile], references: [id])
  id_profile          String        @unique
}

model Delivery {
  id                                  String       @id @default(cuid())
  destination                         Destination? @relation(fields: [id_destination], references: [id])
  id_destination                      String?      @unique
  customer_favouriteDelivery_customer Customer?
}

model Destination {
  id                            String    @id @default(cuid())
  customer_destination_customer Customer? @relation(fields: [customer_number], references: [number])
  customer_number               String?
  delivery_destination_delivery Delivery?
}

model Profile {
  id                         String    @id @default(cuid())
  customer                   Customer?
  collector_profile_customer Customer? @relation(name: "collector", fields: [customer_numbner], references: [number])
  customer_numbner           String?
}
{
    const where: G.CustomerWhereUniqueInput = { number: '1' };
    const updateCustomerInput: G.CustomerUpdateInput = {};
    void $prisma.customer.update({ where, data: updateCustomerInput });
}

If I delete anything from any model it will make tsc happy.

Looks like some kind of recursion of type check. Maybe it's limitation of typescript (it cannot resolve recursion references), l'll try to find related issue in https://github.com/microsoft/TypeScript/issues

unlight avatar Oct 29 '21 20:10 unlight

Hmm.. Any way to bypass this "maybe tsc bug" in the meantime (like disabling specific tsc rules)?

TMInnovations avatar Oct 30 '21 15:10 TMInnovations

Any way to bypass this

You can skip type check here, by converting to any and then to Prisma.CustomerUpdateInput or you can create new variable with type Prisma.CustomerUpdateInput and assign primitive properties from Generated.CustomerUpdateInput There are some tools: class-transformer (classtoplain/plainToClass), nartc/mapper

P.S.

    let updateCustomerInput: G.CustomerUpdateInput = {};
 // error TS2321: Excessive stack depth comparing types 'ProfileUpdateOneRequiredWithoutCustomerInput | undefined' and 'ProfileUpdateOneRequiredWithoutCustomerInput | undefined'
    let p_updateCustomerInput: Prisma.CustomerUpdateInput = {
        profile: updateCustomerInput.profile,
    };

A lot of unresolved issues - https://github.com/microsoft/TypeScript/issues?q=is%3Aissue+sort%3Aupdated-desc+Excessive+stack+depth+comparing+types Looks like it the source of incompatibility issue.

unlight avatar Oct 30 '21 15:10 unlight

Thank you for the quick response. So the next step is to wait until the ts issues are resolved?

TMInnovations avatar Oct 31 '21 09:10 TMInnovations

I doubt that it will be resolved soon.

unlight avatar Oct 31 '21 11:10 unlight

News!

If i add @default(cuid()) to the Customer models @id "number" the initial problem repo works:

Very likely related to be related to: https://github.com/prisma/prisma/issues/10063 and also likely to be related to: https://github.com/prisma/prisma/issues/8776

The thing is: do not have id fields that are NOT autogenerated (@default()) and hidden via @HideField() at the same time. Problem is: I need a default different from cuid() and therefore do the generation of the customer.number in the CreateCustomer resolver. Types of customer.number of Prisma.ParcelUpdateInput and G.ParcelUpdateInput cannot be the same because the graphql input doesn't include the @id field although it's required by prisma, as it's not autogenerated. Does that make sense?

TMInnovations avatar Nov 02 '21 16:11 TMInnovations

I did not get the idea of removing @default.

I almost sure that is TS issue https://github.com/microsoft/TypeScript/issues/29112 https://github.com/microsoft/TypeScript/issues/46631 https://github.com/microsoft/TypeScript/issues/34933

People are saying that downgrading to [email protected] solves the issue, but prisma requires typescript 4+

unlight avatar Nov 02 '21 17:11 unlight

The idea of removing @default is: A customer number should be a string made up of 10 random decimal digits (ex. "1234567890"). cuid() does provide the "random-ness" but not the format that is needed for a customer number. So the customer number cannot be auto-generated with cuid(). As of now I have the customer number created inside a createCustomer mutation resolver (graphql) which then assigns the generated number.

TMInnovations avatar Nov 03 '21 09:11 TMInnovations

@TMInnovations I can suggest solution to solve the issue, but it require patch typescript.

  1. Find tsc.js and following source of code image
  2. Increase targetDepth (or sourceDepth) I was able to get rid of error "Excessive stack depth comparing types" in this schema by changing targetDepth = 200

To automate patching (CI/CD, typescript update), you can use https://github.com/ds300/patch-package

Note: It will fix only cli check, e.g. tsc --noEmit, to fix errors in your IDE or 3rd party libs which using typescript API, you probably need patch all files in typescript/lib/*.

Meanwhile looks like https://github.com/microsoft/TypeScript/issues/34933 this issue is most active in discussing this behavior.

unlight avatar Dec 15 '21 12:12 unlight

Similar problem. Error is highlighted in vscode but project runs

DennieMello avatar Feb 03 '22 16:02 DennieMello

Does anyone have a better solution for this than patching Typescript?

jasonmacdonald avatar Mar 30 '22 17:03 jasonmacdonald

Anyone got found a solution for this?

BrayhanV avatar Jun 29 '23 15:06 BrayhanV