drizzle-orm icon indicating copy to clipboard operation
drizzle-orm copied to clipboard

[BUG]: `"composite" true` and Yarn workspace prevents `pgTable` from being compiled

Open TmLev opened this issue 1 year ago • 4 comments

What version of drizzle-orm are you using?

0.26.1

What version of drizzle-kit are you using?

0.18.1

Describe the Bug

TL;DR

TypeScript can't compile simple schema.ts file with users example table when using "composite": true in tsconfig.json

Longer version

I have Yarn workspace with two packages, let's call them backend and frontend. Naturally, frontend depends on backend. For that to work, backend's tsconfig.json must include "composite": true option.

backend uses drizzle-orm internally for migrations and I would like to use a standalone schema.ts file where all of the tables would be declared. With such setup, I would need to export said tables to use them elsewhere in the code.

This is the moment where export before the users table declaration makes TypeScript compiler think that anyone can import users (type of which depends on inference of drizzle-orm package), even outside of the backend package. Due to lack of export(package) in TypeScript, this leads to compiler errors.

schema.ts
import { pgTable, serial, text, varchar } from "drizzle-orm/pg-core";

export const users = pgTable("users", {
  id: serial("id").primaryKey(),
  fullName: text("full_name"),
  phone: varchar("phone", { length: 256 }),
});
- error TS2742: The inferred type of 'users' cannot be named without a reference to '../../node_modules/drizzle-orm/db.d-2eb7c122'. This is likely not portable. A type annotation is necessary.

3 export const users = pgTable("users", {
               ~~~~~


Found 1 error.

error Command failed with exit code 1.

Expected behavior

Everything compiles just fine.

I found possible workarounds, but none of them are optimal: https://github.com/microsoft/TypeScript/issues/47663#issuecomment-1519138189

Environment & setup

No response

TmLev avatar May 29 '23 12:05 TmLev

@TmLev for the time being, have you settled for an workaround, and if so, which? I am facing the same issue.

alexanderniebuhr avatar Jun 03 '23 19:06 alexanderniebuhr

@alexanderniebuhr I haven't, no. Had to completely remove Drizzle from my backend, sadly. Have you tried the workaround number 3? It seems promising.

UPD: Tried it, doesn't work.

image

TmLev avatar Jun 04 '23 18:06 TmLev

Importing the requested file directly

import * as _drizzle from '../../../../node_modules/drizzle-orm/select.types.d-e43b2599';

turns the error to silent

mlecoq avatar Jun 07 '23 07:06 mlecoq

I don't think you should do that, but if it fixes the error...

TmLev avatar Jun 07 '23 07:06 TmLev

An alternative is to create your own mysqlTable | pgTable method

with mysql

import { mysqlTable as mysqlTableDrizzle } from 'drizzle-orm/mysql-core';

export type Table<
  TableName extends string,
  TConfigMap extends Record<string, AnyMySqlColumnBuilder>,
> = MySqlTableWithColumns<{
  name: TableName;
  schema: undefined;
  columns: BuildColumns<TableName, TConfigMap>;
}>;

export const mysqlTable = <
  TableName extends string,
  TConfigMap extends Record<string, AnyMySqlColumnBuilder>,
>(
  table: TableName,
  columns: TConfigMap,
  extraConfig?: (
    self: BuildColumns<TableName, TConfigMap>,
  ) => MySqlTableExtraConfig,
): Table<TableName, TConfigMap> =>
  mysqlTableDrizzle(table, columns, extraConfig);

mlecoq avatar Jun 09 '23 19:06 mlecoq

An alternative is to create your own mysqlTable | pgTable method

While this sounds promising, I really think it should be possible to fix in the lib layer. Isn't it?

alexanderniebuhr avatar Jun 09 '23 19:06 alexanderniebuhr

it doesn't seem to be an issue related to drizzle so unfortunately no

mlecoq avatar Jun 09 '23 19:06 mlecoq

Since it seems that it can be fixed with changes of the type of exports in the lib code, according to the upstream issue comments, I would think these changes can be made to drizzle to fix it.

If the following statement is true, I think it can be fixed in drizzle side, with changing this pattern.

Any npm package whose types reference another npm package's type will generate the error

alexanderniebuhr avatar Jun 09 '23 19:06 alexanderniebuhr

It's just a way to use workaround 2 as described here https://github.com/microsoft/TypeScript/issues/47663#issuecomment-1519138189

mlecoq avatar Jun 09 '23 19:06 mlecoq

That's correct, but which other package is drizzle referencing the types from. If we know this, we should just be able to install it in addition.

alexanderniebuhr avatar Jun 09 '23 19:06 alexanderniebuhr

I just accidentally found an workaround, adding the line to any file with the error, fixes it for me. @TmLev can you validate?

import type { PgTableWithColumns, TableConfig } from 'drizzle-orm/pg-core'
type unused = PgTableWithColumns<TableConfig>

alexanderniebuhr avatar Jun 16 '23 17:06 alexanderniebuhr

Could you supply a minimal reproduction repo? Would like to take a look at it :)

pkerschbaum avatar Jun 17 '23 15:06 pkerschbaum

I will, in a few hours

TmLev avatar Jun 17 '23 15:06 TmLev

Could you supply a minimal reproduction repo?

@pkerschbaum sure!

  • https://stackblitz.com/github/alexanderniebuhr/drizzle-repro
  • https://github.com/alexanderniebuhr/drizzle-repro

You can use following command:

pnpm --filter db start

The file with the issue is:

packages/db/src/schema/products.ts

alexanderniebuhr avatar Jun 17 '23 18:06 alexanderniebuhr

I just accidentally found an workaround, adding the line to any file with the error, fixes it for me. @TmLev can you validate?

import type { PgTableWithColumns, TableConfig } from 'drizzle-orm/pg-core'
type unused = PgTableWithColumns<TableConfig>

I can confirm that this fixes the issue for me.

nicu-chiciuc avatar Jun 20 '23 09:06 nicu-chiciuc

I finally looked into it and workaround #3.1 of https://github.com/microsoft/TypeScript/issues/47663#issuecomment-1519138189 could also be applied (PgTableWithColumns must be made available by exporting it), that would fix it in the library itself.

See https://github.com/pkerschbaum/drizzle-repro/compare/main...fix/patch-for-drizzle-orm for the changes.

I would suggest that drizzle-orm applies this to easen the burden of pnpm users.

pkerschbaum avatar Jul 15 '23 15:07 pkerschbaum

I've got a pretty similar error for relations. Screenshot 2023-07-17 at 22 11 37

Literally adding export in front of Relations, One, and Many inside query-promise.d resolved the issue.

export declare class Relations<TTableName extends string = string, TConfig extends Record<string, Relation> = Record<string, Relation>> {
    readonly table: AnyTable<{
        name: TTableName;
    }>;
    readonly config: (helpers: TableRelationsHelpers<TTableName>) => TConfig;
    static readonly [entityKind]: string;
    readonly $brand: 'Relations';
    constructor(table: AnyTable<{
        name: TTableName;
    }>, config: (helpers: TableRelationsHelpers<TTableName>) => TConfig);
}
export declare class One<TTableName extends string = string, TIsNullable extends boolean = boolean> extends Relation<TTableName> {
    readonly config: RelationConfig<TTableName, string, AnyColumn<{
        tableName: TTableName;
    }>[]> | undefined;
    readonly isNullable: TIsNullable;
    static readonly [entityKind]: string;
    protected $relationBrand: 'One';
    constructor(sourceTable: Table, referencedTable: AnyTable<{
        name: TTableName;
    }>, config: RelationConfig<TTableName, string, AnyColumn<{
        tableName: TTableName;
    }>[]> | undefined, isNullable: TIsNullable);
    withFieldName(fieldName: string): One<TTableName>;
}
export declare class Many<TTableName extends string> extends Relation<TTableName> {
    readonly config: {
        relationName: string;
    } | undefined;
    static readonly [entityKind]: string;
    protected $relationBrand: 'Many';
    constructor(sourceTable: Table, referencedTable: AnyTable<{
        name: TTableName;
    }>, config: {
        relationName: string;
    } | undefined);
    withFieldName(fieldName: string): Many<TTableName>;
}

MateWW avatar Jul 17 '23 20:07 MateWW

@alexanderniebuhr had the same issue, fixed after I changed "moduleResolution" from "NodeNext" to "Node"

dn-l avatar Jul 25 '23 07:07 dn-l

fixed after I changed "moduleResolution" from "NodeNext" to "Node"

Thanks for the info. However that is a change, not everyone can do!

alexanderniebuhr avatar Jul 25 '23 17:07 alexanderniebuhr

I've got a pretty similar error for relations. Screenshot 2023-07-17 at 22 11 37

Literally adding export in front of Relations, One, and Many inside query-promise.d resolved the issue.

export declare class Relations<TTableName extends string = string, TConfig extends Record<string, Relation> = Record<string, Relation>> {
    readonly table: AnyTable<{
        name: TTableName;
    }>;
    readonly config: (helpers: TableRelationsHelpers<TTableName>) => TConfig;
    static readonly [entityKind]: string;
    readonly $brand: 'Relations';
    constructor(table: AnyTable<{
        name: TTableName;
    }>, config: (helpers: TableRelationsHelpers<TTableName>) => TConfig);
}
export declare class One<TTableName extends string = string, TIsNullable extends boolean = boolean> extends Relation<TTableName> {
    readonly config: RelationConfig<TTableName, string, AnyColumn<{
        tableName: TTableName;
    }>[]> | undefined;
    readonly isNullable: TIsNullable;
    static readonly [entityKind]: string;
    protected $relationBrand: 'One';
    constructor(sourceTable: Table, referencedTable: AnyTable<{
        name: TTableName;
    }>, config: RelationConfig<TTableName, string, AnyColumn<{
        tableName: TTableName;
    }>[]> | undefined, isNullable: TIsNullable);
    withFieldName(fieldName: string): One<TTableName>;
}
export declare class Many<TTableName extends string> extends Relation<TTableName> {
    readonly config: {
        relationName: string;
    } | undefined;
    static readonly [entityKind]: string;
    protected $relationBrand: 'Many';
    constructor(sourceTable: Table, referencedTable: AnyTable<{
        name: TTableName;
    }>, config: {
        relationName: string;
    } | undefined);
    withFieldName(fieldName: string): Many<TTableName>;
}

We were able to fix the issue using this suggestion and locally patching drizzle-orm using pnpm patch.

nick-kang avatar Aug 06 '23 05:08 nick-kang

should be reopened, I don't think my PR fixed it completely.

alexanderniebuhr avatar Aug 16 '23 13:08 alexanderniebuhr

Setting the following to false in ts.config fixed it for me

"declaration": false,
"declarationMap": false,
"composite": false,

rweilg avatar Aug 20 '23 19:08 rweilg

Setting the following to false in ts.config fixed it for me

Yes it does. But it should work with any setting. I need all of them to be true

alexanderniebuhr avatar Aug 21 '23 04:08 alexanderniebuhr