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

[BUG]: types not properly exported (esm) & not portable

Open alexn-s opened this issue 1 year ago • 3 comments

What version of drizzle-orm are you using?

0.25.3

What version of drizzle-kit are you using?

0.17.6

Describe the Bug

bug

23-04-28_12-23-11_601 _ Code _ schema ts_-noco-life-prefix-_Visual_Studio_Code

file with error

import {
	datetime,
	foreignKey,
	index,
	int,
	mysqlEnum,
	mysqlTable,
	text,
	timestamp,
	varchar,
} from 'drizzle-orm/mysql-core';
...

in module mysql-core

fix

prefix all types with export. in general it is good practice to export types from a lib to avoid ts/ intellisense errors

example \node_modules.pnpm\[email protected][email protected]\node_modules\drizzle-orm\select.types.d-ffd2e526.d.ts

...

export type MySqlTableExtraConfig = Record<string, AnyIndexBuilder | CheckBuilder | ForeignKeyBuilder | PrimaryKeyBuilder>;
export type TableConfig = TableConfig$1<AnyMySqlColumn>;
declare class MySqlTable<T extends TableConfig> extends Table<T> {
    protected $columns: T['columns'];
}
export type AnyMySqlTable<TPartial extends Partial<TableConfig> = {}> = MySqlTable<UpdateTableConfig<TableConfig, TPartial>>;
export type MySqlTableWithColumns<T extends TableConfig> = MySqlTable<T> & {
    [Key in keyof T['columns']]: T['columns'][Key];
};
...

from a blog about exporting types

In a TypeScript library, it's generally a good practice to export the types, especially if the library is intended to be used by other developers. By exporting types, you provide additional documentation and make it easier for users of your library to consume it correctly.

Exporting types also enables consumers of the library to benefit from the type checking and auto-completion features provided by TypeScript, which can save time and reduce errors.

However, if you're building a small library for your own use and don't anticipate it being used by other developers, exporting types may not be necessary.

please let me know if my thoughts are wrong or if there is a reason for not exporting the types. i appreciate your work

@dankochetov #511

Expected behavior

No response

Environment & setup

No response

alexn-s avatar Apr 28 '23 10:04 alexn-s

Any update on this? I have to patch drizzle (0.26.0) for every version now.

This is what I have to patch to compile with tsc (postgres).

diff --git a/db.d-bc9a1d6c.d.ts b/db.d-bc9a1d6c.d.ts
index 2fa88f9a50a2530c82ba1f55ceb6302d691c4d46..4e66ee8bc590ed92686e1e3203d000f4da03ea2d 100644
--- a/db.d-bc9a1d6c.d.ts
+++ b/db.d-bc9a1d6c.d.ts
@@ -180,7 +180,7 @@ type AnyPgTable<TPartial extends Partial<TableConfig> = {}> = PgTable<UpdateTabl
 interface AnyPgTableHKT extends AnyTableHKT {
     type: AnyPgTable<Assume<this['config'], Partial<TableConfig>>>;
 }
-type PgTableWithColumns<T extends TableConfig> = PgTable<T> & {
+export type PgTableWithColumns<T extends TableConfig> = PgTable<T> & {
     [Key in keyof T['columns']]: T['columns'][Key];
 };
 interface PgTableFn<TSchema extends string | undefined = undefined> {

bjon avatar May 20 '23 12:05 bjon

by the way, this is my patch for mysql with pnpm patch workflow for people with the same issue

cli commands to patch a package

pnpm patch drizzle-orm pnpm patch-commit PATH_TO_DIR

package.json

	"pnpm": {
		"patchedDependencies": {
			"[email protected]": "patches/[email protected]"
		}
	},

patch

diff --git a/select.types.d-ffd2e526.d.ts b/select.types.d-ffd2e526.d.ts
index 3ec41518bedb031a038b4e3c50b4252f501aab08..3e656a1ce09d2930837eef7a96eeeb466ce64118 100644
--- a/select.types.d-ffd2e526.d.ts
+++ b/select.types.d-ffd2e526.d.ts
@@ -38,7 +38,7 @@ interface IndexConfig {
      */
     lock?: 'default' | 'none' | 'shared' | 'exclusive';
 }
-type IndexColumn = AnyMySqlColumn | SQL;
+export type IndexColumn = AnyMySqlColumn | SQL;
 declare class IndexBuilderOn {
     private name;
     private unique;
@@ -62,7 +62,7 @@ declare class Index {
     };
     constructor(config: IndexConfig, table: AnyMySqlTable);
 }
-type GetColumnsTableName<TColumns> = TColumns extends AnyMySqlColumn<{
+export type GetColumnsTableName<TColumns> = TColumns extends AnyMySqlColumn<{
     tableName: infer TTableName extends string;
 }> | AnyMySqlColumn<{
     tableName: infer TTableName extends string;
@@ -83,13 +83,13 @@ declare class PrimaryKey {
     getName(): string;
 }
 
-type MySqlTableExtraConfig = Record<string, AnyIndexBuilder | CheckBuilder | ForeignKeyBuilder | PrimaryKeyBuilder>;
-type TableConfig = TableConfig$1<AnyMySqlColumn>;
+export type MySqlTableExtraConfig = Record<string, AnyIndexBuilder | CheckBuilder | ForeignKeyBuilder | PrimaryKeyBuilder>;
+export type TableConfig = TableConfig$1<AnyMySqlColumn>;
 declare class MySqlTable<T extends TableConfig> extends Table<T> {
     protected $columns: T['columns'];
 }
-type AnyMySqlTable<TPartial extends Partial<TableConfig> = {}> = MySqlTable<UpdateTableConfig<TableConfig, TPartial>>;
-type MySqlTableWithColumns<T extends TableConfig> = MySqlTable<T> & {
+export type AnyMySqlTable<TPartial extends Partial<TableConfig> = {}> = MySqlTable<UpdateTableConfig<TableConfig, TPartial>>;
+export type MySqlTableWithColumns<T extends TableConfig> = MySqlTable<T> & {
     [Key in keyof T['columns']]: T['columns'][Key];
 };
 declare function mysqlTableWithSchema<TTableName extends string, TSchemaName extends string | undefined, TColumnsMap extends Record<string, AnyMySqlColumnBuilder>>(name: TTableName, columns: TColumnsMap, extraConfig: ((self: BuildColumns<TTableName, TColumnsMap>) => MySqlTableExtraConfig) | undefined, schema: TSchemaName, baseName?: TTableName): MySqlTableWithColumns<{
@@ -107,8 +107,8 @@ interface MySqlTableFn<TSchemaName extends string | undefined = undefined> {
 declare const mysqlTable: MySqlTableFn;
 declare function mysqlTableCreator(customizeTableName: (name: string) => string): MySqlTableFn;
 
-type UpdateDeleteAction = 'cascade' | 'restrict' | 'no action' | 'set null' | 'set default';
-type Reference = () => {
+export type UpdateDeleteAction = 'cascade' | 'restrict' | 'no action' | 'set null' | 'set default';
+export type Reference = () => {
     readonly columns: AnyMySqlColumn[];
     readonly foreignTable: AnyMySqlTable;
     readonly foreignColumns: AnyMySqlColumn[];
@@ -124,7 +124,7 @@ declare class ForeignKeyBuilder {
     onUpdate(action: UpdateDeleteAction): this;
     onDelete(action: UpdateDeleteAction): this;
 }
-type AnyForeignKeyBuilder = ForeignKeyBuilder;
+export type AnyForeignKeyBuilder = ForeignKeyBuilder;
 declare class ForeignKey {
     readonly table: AnyMySqlTable;
     readonly reference: Reference;
@@ -307,7 +307,7 @@ type WithSubqueryWithSelection<TSelection extends ColumnsSelection, TAlias exten
 declare class MySqlDatabase<TQueryResult extends QueryResultHKT, TPreparedQueryHKT extends PreparedQueryHKTBase> {
     constructor(
     /** @internal */
-    dialect: MySqlDialect, 
+    dialect: MySqlDialect,
     /** @internal */
     session: MySqlSession<any, any>);
     $with<TAlias extends string>(alias: TAlias): {
@@ -432,7 +432,7 @@ declare abstract class MySqlSelectQueryBuilder<THKT extends MySqlSelectHKTBase,
     protected config: MySqlSelectConfig;
     protected joinsNotNullableMap: Record<string, boolean>;
     private tableName;
-    constructor(table: MySqlSelectConfig['table'], fields: MySqlSelectConfig['fields'], isPartialSelect: boolean, 
+    constructor(table: MySqlSelectConfig['table'], fields: MySqlSelectConfig['fields'], isPartialSelect: boolean,
     /** @internal */
     session: MySqlSession | undefined, dialect: MySqlDialect, withList: Subquery[]);
     private createJoin;

alexn-s avatar May 20 '23 17:05 alexn-s

With the new "Relational queries", I have to export more types.

  "pnpm": {
    "patchedDependencies": {
      "[email protected]": "patches/[email protected]"
    }
  }
diff --git a/db.d-bc9a1d6c.d.ts b/db.d-bc9a1d6c.d.ts
index 2fa88f9a50a2530c82ba1f55ceb6302d691c4d46..4e66ee8bc590ed92686e1e3203d000f4da03ea2d 100644
--- a/db.d-bc9a1d6c.d.ts
+++ b/db.d-bc9a1d6c.d.ts
@@ -180,7 +180,7 @@ type AnyPgTable<TPartial extends Partial<TableConfig> = {}> = PgTable<UpdateTabl
 interface AnyPgTableHKT extends AnyTableHKT {
     type: AnyPgTable<Assume<this['config'], Partial<TableConfig>>>;
 }
-type PgTableWithColumns<T extends TableConfig> = PgTable<T> & {
+export type PgTableWithColumns<T extends TableConfig> = PgTable<T> & {
     [Key in keyof T['columns']]: T['columns'][Key];
 };
 interface PgTableFn<TSchema extends string | undefined = undefined> {
diff --git a/query-promise.d-e370e0a9.d.ts b/query-promise.d-e370e0a9.d.ts
index 41f38369afa0b7cc8deb82247e96c91982e6357a..99a3bae1a13a16fb07b02e4177a20c5d2ec9ad11 100644
--- a/query-promise.d-e370e0a9.d.ts
+++ b/query-promise.d-e370e0a9.d.ts
@@ -440,7 +440,7 @@ declare abstract class Relation<TTableName extends string = string> {
     }>, relationName: string | undefined);
     abstract withFieldName(fieldName: string): Relation<TTableName>;
 }
-declare class Relations<TTableName extends string = string, TConfig extends Record<string, Relation> = Record<string, Relation>> {
+export declare class Relations<TTableName extends string = string, TConfig extends Record<string, Relation> = Record<string, Relation>> {
     readonly table: AnyTable<{
         name: TTableName;
     }>;
@@ -450,7 +450,7 @@ declare class Relations<TTableName extends string = string, TConfig extends Reco
         name: TTableName;
     }>, config: (helpers: TableRelationsHelpers<TTableName>) => TConfig);
 }
-declare class One<TTableName extends string = string, TIsNullable extends boolean = boolean> extends Relation<TTableName> {
+export declare class One<TTableName extends string = string, TIsNullable extends boolean = boolean> extends Relation<TTableName> {
     readonly config: RelationConfig<TTableName, string, AnyColumn<{
         tableName: TTableName;
     }>[]> | undefined;
@@ -463,7 +463,7 @@ declare class One<TTableName extends string = string, TIsNullable extends boolea
     }>[]> | undefined, isNullable: TIsNullable);
     withFieldName(fieldName: string): One<TTableName>;
 }
-declare class Many<TTableName extends string> extends Relation<TTableName> {
+export declare class Many<TTableName extends string> extends Relation<TTableName> {
     readonly config: {
         relationName: string;
     } | undefined;

bjon avatar May 24 '23 14:05 bjon

I encountered this when putting the moduleResolution in my tsconfig.json on either nodenext and node16. When can this patch be merged?

jessielaf avatar Jun 27 '23 08:06 jessielaf

I can confirm Bjon's workaround works. This fixes the drizzle-orm bug described here: https://github.com/drizzle-team/drizzle-orm/issues/656

mkoreo avatar Jul 09 '23 08:07 mkoreo

IMO the patches are hiding the real problem. All the types are exported at the bottom of the files, but with an alias (so patching an export just exports it twice). They should however be exported without an alias, I proposed a MR to fix that. Let's hope it will get merged.

alexanderniebuhr avatar Jul 15 '23 19:07 alexanderniebuhr

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

alexanderniebuhr avatar Aug 16 '23 13:08 alexanderniebuhr

Confirmed it is still an issue on beta release. Was able to make a very small reproduction https://github.com/RTVision/drizzle-esm-type-error

Issue occurs outside of a monorepo with npm or pnpm. Main driver here is just having typescript use Node16+ module resolution with NodeNext/Node16/Bundler module resolutions

kalvenschraut avatar Aug 17 '23 00:08 kalvenschraut