objection.js icon indicating copy to clipboard operation
objection.js copied to clipboard

A problem with typescript version 4

Open vh-dao opened this issue 4 years ago • 24 comments

Hi, objection.js is a great tool. I am using latest version of knex and typescript, so want to use objection@next but it is throwing error:

           throw e;
                ^
RangeError: Maximum call stack size exceeded
    at compareSignaturesRelated (\node_modules\typescript\lib\tsc.js:50982:27)
    at signatureRelatedTo (\node_modules\typescript\lib\tsc.js:52833:24)
    at signaturesRelatedTo (\node_modules\typescript\lib\tsc.js:52776:39)
    at structuredTypeRelatedToWorker (\node_modules\typescript\lib\tsc.js:52309:39)
    at structuredTypeRelatedTo (\node_modules\typescript\lib\tsc.js:51954:30)
    at recursiveTypeRelatedTo (\node_modules\typescript\lib\tsc.js:51930:53)
    at isRelatedTo (\node_modules\typescript\lib\tsc.js:51527:34)
    at isPropertySymbolTypeRelated (\node_modules\typescript\lib\tsc.js:52488:24)
    at propertyRelatedTo (\node_modules\typescript\lib\tsc.js:52520:31)
    at propertiesRelatedTo (\node_modules\typescript\lib\tsc.js:52708:43)

package.json:

        "objection": "^3.0.0-alpha.5",
        "typescript": "^4.4.4"

Which version of objection.js and typescript should I use?

vh-dao avatar Oct 30 '21 04:10 vh-dao

Objection v3 is still alpha version meaning that it is still not complete, you can use version 2.2.15 which is stable and I use typescript version 4.3.5

abedmurrar avatar Nov 01 '21 05:11 abedmurrar

Objection v3 is still alpha version meaning that it is still not complete, you can use version 2.2.15 which is stable and I use typescript version 4.3.5

It still does not work, it throws error:

node_modules/objection/typings/objection/index.d.ts:1839:12 - error TS2709: Cannot use namespace 'Knex' as a type.

1839     (knex: Knex, modelClasses: AnyModelConstructor[]): Promise<void>;
                ~~~~

I fixed by adding skipLibCheck in tsconfig.json but it is not a good solution:

// tsconfig.js
	"compilerOptions": {
		"skipLibCheck": true
         }

vh-dao avatar Nov 01 '21 09:11 vh-dao

@vh-dao Please check upgrading guide for Knex, I think you are using latest version in a wrong way.

kibertoad avatar Nov 01 '21 09:11 kibertoad

Can you try objection next, knex 0.95, ts 4.4 and share code which is throwing an error?

kibertoad avatar Nov 01 '21 09:11 kibertoad

I'm having this issue with circular dependencies in relationMappings. Because I am using ESM the require loop solution does not work.

import { Model } from 'objection'
import { AuthenticationMethod } from './AuthenticationMethod';

export class Account extends Model {
  id: string
  email: string
  
  static get tableName() {
    return 'accounts';
  }

  static relationMappings() {
    return {
      authenticationMethods: {
        relation: Model.HasManyRelation,
        modelClass: AuthenticationMethod,
        join: {
          from: 'accounts.id',
          to: 'authentication_methods.account_id'
        }
      }
    }
  }
}
import { Model}  from 'objection'
import { Account}  from './Account'

export class AuthenticationMethod extends Model {
  static get tableName() {
    return 'authentication_methods'
  }

  static get relationMappings() {
    return {
      account: {
        relation: Model.BelongsToOneRelation,
        modelClass: Account,
        join: {
          from: 'authentication_methods.account_id',
          to: 'accounts.id'
        }
      }
    }
  }
}

➜  dev-server git:(master) ✗ tsc                
/usr/lib/node_modules/typescript/lib/tsc.js:92656
                throw e;
                ^

RangeError: Maximum call stack size exceeded
    at String.replace (<anonymous>)
    at /usr/lib/node_modules/typescript/lib/tsc.js:51887:90
    at Array.map (<anonymous>)
    at recursiveTypeRelatedTo (/usr/lib/node_modules/typescript/lib/tsc.js:51887:62)
    at isRelatedTo (/usr/lib/node_modules/typescript/lib/tsc.js:51527:34)
    at typeArgumentsRelatedTo (/usr/lib/node_modules/typescript/lib/tsc.js:51834:39)
    at relateVariances (/usr/lib/node_modules/typescript/lib/tsc.js:52341:34)
    at structuredTypeRelatedToWorker (/usr/lib/node_modules/typescript/lib/tsc.js:52289:46)
    at structuredTypeRelatedTo (/usr/lib/node_modules/typescript/lib/tsc.js:51954:30)
    at recursiveTypeRelatedTo (/usr/lib/node_modules/typescript/lib/tsc.js:51930:53)
➜  dev-server git:(master) ✗ tsc -v
Version 4.4.4
  "dependencies": {
    "knex": "^0.95.12",
    "objection": "^3.0.0-rc.2"
  },

Edit: It doesn't seem to necessarily be a circular dependency problem, because removing the parent relationship from the child does not solve the problem.

Edit2: Removing any attributes from the child (e.g. id: string) removes the compilation error but obviously will result in runtime errors.

stefanvanherwijnen avatar Nov 07 '21 13:11 stefanvanherwijnen

Can you try objection next, knex 0.95, ts 4.4 and share code which is throwing an error?

The error I reported are object@next and typescript v4.4

package.json:
        "objection": "^3.0.0-alpha.5",
        "typescript": "^4.4.4"

vh-dao avatar Nov 08 '21 01:11 vh-dao

I can't reproduce this. I really need a working reproduction or there's nothing I can do. Latest objection@next is now tested agains typescript 4.4.4 and all tests pass.

koskimas avatar Nov 08 '21 08:11 koskimas

Reproduction: https://github.com/stefanvanherwijnen/objection-repro-2132

stefanvanherwijnen avatar Nov 08 '21 10:11 stefanvanherwijnen

You are not running typescript in strict mode. Add strict: true to tsconfig.

koskimas avatar Nov 08 '21 13:11 koskimas

I'm running into this issue with the released version of 3.0.0

@koskimas are you saying that objection 3 requires strict: true to work properly with typescript? Is that documented anywhere? It seems like a pretty significant limitation.

jhiesey avatar Nov 10 '21 23:11 jhiesey

I don't think strict is required, but it will point out any errors in your model files. In my case the solution was to properly define the properties with the ! operator, e.g. id!: string

Edit: Actually, strict is required for compilation.

stefanvanherwijnen avatar Nov 11 '21 08:11 stefanvanherwijnen

@stefanvanherwijnen is it documented anywhere that strict: true must be specified in the tsconfig? I'm not currently using strict mode with versions prior to V3 and didn't have any issues.

elby22 avatar Nov 22 '21 15:11 elby22

No I don't think so. But in my case without strict: true I get the error which this issue is about, with it I don't. It might be introduced in V3 but I think @koskimas should clear this up or document it.

stefanvanherwijnen avatar Nov 22 '21 16:11 stefanvanherwijnen

This issue should be reopened. The culprit is one of these typings:

type PartialModelObject<T extends Model> = {
  [K in NonFunctionPropertyNames<T>]?: Defined<T[K]> extends Model
    ? T[K]
    : Defined<T[K]> extends Array<infer I>
    ? I extends Model
      ? I[]
      : Expression<T[K]>
    : Expression<T[K]>;
};

type PartialModelGraph<M, T = M & GraphParameters> = {
  [K in NonFunctionPropertyNames<T>]?: Defined<T[K]> extends Model
    ? PartialModelGraph<Defined<T[K]>>
    : Defined<T[K]> extends Array<infer I>
    ? I extends Model
      ? PartialModelGraph<I>[]
      : Expression<T[K]>
    : Expression<T[K]>;
};

when I change one of them to any the project compiles fine. But I couldn't figure out which code line or model triggers it yet.

INFO:

node: 16.13.0
knex: 0.95.14
objection: 3.0.0
typescript: 4.5.4

ayZagen avatar Dec 18 '21 16:12 ayZagen

@koskimas I think the issue is caused by NonFunctionPropertyNames including QueryBuilderType. It should go away by excluding QueryBuilderType in PartialModelObject and PartialModelGraph:

  type PartialModelObject<T extends Model> = {
    [K in Exclude<NonFunctionPropertyNames<T>, 'QueryBuilderType'>]?: Defined<T[K]> extends Model
      ? T[K]
      : Defined<T[K]> extends Array<infer I>
      ? I extends Model
        ? I[]
        : Expression<T[K]>
      : Expression<T[K]>;
  };

I'm not sure why I also needed T extends any for PartialModelGraph, probably some weird union issue:

  type PartialModelGraph<M, T = M & GraphParameters> = T extends any ? {
    [K in Exclude<NonFunctionPropertyNames<T>, 'QueryBuilderType'>]?: Defined<T[K]> extends Model
      ? PartialModelGraph<Defined<T[K]>>
      : Defined<T[K]> extends Array<infer I>
      ? I extends Model
        ? PartialModelGraph<I>[]
        : Expression<T[K]>
      : Expression<T[K]>;
  } : never;

Linksku avatar Dec 28 '21 09:12 Linksku

Thank you @Linksku! Great work! I'll try this soon and release a new version if it works!

koskimas avatar Dec 30 '21 23:12 koskimas

That fix is now implemented in 3.0.1. Please try it out and report back to me if the issue is gone

koskimas avatar Dec 30 '21 23:12 koskimas

Thanks! I still need T extends any to avoid Maximum call stack size exceeded. Maybe my types are just weird and it works for other people without that

Linksku avatar Dec 31 '21 08:12 Linksku

Hmm... That's weird. Could you create a reproduction for me? For some reason I'm unable to reproduce any of these typescript problems. Probably due to my tsconfig being different.

koskimas avatar Jan 02 '22 18:01 koskimas

Hi! Same as @Linksku, I also need to wrap the declaration of PartialModelGraph with T extends any ? ... : never. If I don't do this, the types of "nested" models (from relationMappings) in a model graph are not inferred by TypeScript. However, I do not face a Maximum call stack size exceeded error when compiling my project without this fix:

type PartialModelGraph<M, T = M & GraphParameters> = T extends any ? {
    [K in DataPropertyNames<T>]?: Defined<T[K]> extends Model
      ? PartialModelGraph<Defined<T[K]>>
      : Defined<T[K]> extends Array<infer I>
      ? I extends Model
        ? PartialModelGraph<I>[]
        : Expression<T[K]>
      : Expression<T[K]>;
  } : never;

@koskimas: Cloud you release a new version with the T extends any ? ... : never fix? I would be very grateful! :-)

FYI: It does not matter if I set strict: true or strict: false in my tsconfig.json file - in both cases, I still need the T extends any ? ... : never fix.

Package versions:

typescript: 4.5.4
objection: 3.0.1
knex: 0.95.15

flohil avatar Jan 07 '22 12:01 flohil

I was getting the same maximum stack error with typescript 4.5.5, no direct errors were showing until i reduced the project to one model i'm getting

permission.model.ts:6:22 - error TS2321: Excessive stack depth comparing types 'UpsertGraphMethod<?>' and 'UpsertGraphMethod<?>'.

i also can no longer chain .throwIfNotFound() and manually have to check:

await Activity
        .query(trx)
        .findById(req.params.id)
        // .throwIfNotFound({message: 'Activity not found.'})  no longer works
        .then(async (activity: Activity | undefined) => {

            if (!activity)
              throw new NotFoundError({message: 'Activity not found.'})

m-row avatar Feb 01 '22 19:02 m-row

Hi, I have the same issue. Also fixed with the T extends any ? ... : never fix. Please can you release a new version with this included?

lewilewilewi avatar Feb 10 '22 00:02 lewilewilewi

I am getting the same error on Typescript 4.5.5 as well. I was able to get rid of the problem by setting strictNullChecks: false in tsconfig.json as mentioned in related issue but it's just a temporary fix.

aolvictim avatar Feb 10 '22 15:02 aolvictim

Hey, Can we please implement the fix from @Linksku ? It works for me and stops all my projects breaking...

lewilewilewi avatar May 04 '22 18:05 lewilewilewi

I managed to reproduce the endless recursion on v3.0.2 on the test-case provided by @stefanvanherwijnen here. I can confirm that the fix from @Linksku as summarized here does indeed fix it.

I am going to add this fix.

lehni avatar Apr 14 '23 23:04 lehni