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

[BUG]: type obtained with $inferInsert is empty

Open xegulon opened this issue 1 year ago • 30 comments

What version of drizzle-orm are you using?

0.32.0

What version of drizzle-kit are you using?

0.23.0

Describe the Bug

I defined a users table in my drizzle schema, and the NewUser type obtained with users.$inferInsert is empty:

image

Expected behavior

NewUser type should have most of the users table properties.

Environment & setup

Fedora Linux node-postgres typescript: 5.5.3

xegulon avatar Jul 15 '24 13:07 xegulon

I encountered the same issue in drizzle-orm version 0.32.0, which was resolved after downgrading to version 0.31.4

mohammadraasel avatar Jul 17 '24 07:07 mohammadraasel

Could you please send a schema as code snippet, so I can test with it?

AndriiSherman avatar Jul 17 '24 09:07 AndriiSherman

Could you please send a schema as code snippet, so I can test with it?

import {type InferInsertModel} from 'drizzle-orm';
import {pgTable} from 'drizzle-orm/pg-core';

const Users = pgTable('users', {
  id: serial('id').primaryKey(),
  firstName: text('first_name'),
  lastName: text('last_name'),
  email: text('email'),
});

type NewUserType = InferInsertModel<typeof Users>;

@AndriiSherman the type of NewUserType would be an empty object

masterchief-Dave avatar Jul 18 '24 10:07 masterchief-Dave

Could you please send a schema as code snippet, so I can test with it?

@AndriiSherman

import {
  serial,
  text,
  timestamp,
  pgTable,
  boolean,
  pgEnum,
} from 'drizzle-orm/pg-core';

export const roleEnum = pgEnum('role', ['admin', 'student']);

export const users = pgTable('user', {
  id: serial('id').primaryKey(),
  emailValidated: boolean('email_validated').default(false),
  email: text('email').unique('user_email_unique'),
  firstName: text('first_name'),
  lastName: text('last_name'),
  password: text('password'),
  role: roleEnum('role').default('student'),
  createdAt: timestamp('created_at'),
  updatedAt: timestamp('updated_at'),
});

export type User = typeof users.$inferSelect;

export type NewUser = typeof users.$inferInsert;

xegulon avatar Jul 18 '24 14:07 xegulon

Is there an intermediate solution for this other than reducing drizzle-orm version ?

mandarzope avatar Jul 19 '24 14:07 mandarzope

I'm having this issue and then some:

  • $inferInsert only provides fields that are notNull() or generated by default
  • $inferSelect does not respect nullability of fields and the type has every field as required

Also on 0.32.0 orm & 0.23.0 kit

miloAtKndrd avatar Jul 23 '24 13:07 miloAtKndrd

I'm trying to add examples for @xegulon and @davieoba to the type tests. I can confirm that I see all the types properly. There might be an issue with the TypeScript setup. Could you share your tsconfig files and TypeScript version so I can reproduce the issue properly?

AndriiSherman avatar Jul 23 '24 14:07 AndriiSherman

Sure!

tsconfig below, typescript is version ^5.3.3

{
  "compilerOptions": {
    "outDir": "dist",
    "incremental": true,
    "target": "es2017",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noUnusedLocals": false,
    "noImplicitAny": false,
    "sourceMap": true,
    "lib": ["ESNext"],
    "strictNullChecks": false,
    "inlineSources": true,

    // Set `sourceRoot` to  "/" to strip the build path prefix
    // from generated source code references.
    // This improves issue grouping in Sentry.
    "sourceRoot": "/"
  },
  "compileOnSave": true,
  "include": ["src"]
}

miloAtKndrd avatar Jul 23 '24 15:07 miloAtKndrd

Sure, here it is @AndriiSherman:

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "ES2021",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": false
  }
}

And "typescript": "5.5.3".

xegulon avatar Jul 23 '24 15:07 xegulon

oh you didn't ask for mine lol sorry. but i have exactly the same issue and there's my setup anyway

miloAtKndrd avatar Jul 23 '24 15:07 miloAtKndrd

Is there an intermediate solution for this other than reducing drizzle-orm version ?

Defining your insert type manually can be a solution maybe?

xegulon avatar Jul 23 '24 16:07 xegulon

Agreed. Defining the insert types manually and declaring any type while inserting/updating the records.

db.insert(users).values(userObj as any)
db.update(users).set(userObj as any)

mandarzope avatar Jul 23 '24 18:07 mandarzope

I'm having this issue and then some:

* `$inferInsert` only provides fields that are `notNull()` or generated by default

* `$inferSelect` does not respect nullability of fields and the type has every field as required

Also on 0.32.0 orm & 0.23.0 kit

Hi! I have the same issue described here, and I have a feeling that this is a problem coming from TS, because it's not only affecting drizzle but also affecting others libraries inferring types like elysiajs. The main thing to note is that the issue appeared after I migrated to a NX monorepo. Now, my TS config is split between multiple files that are extending and referencing each others. I tried downgrading TS or drizzle, but the issue is still here. I will try to make a reproduction repo.

EDIT: Even my projects that aren't in a monorepo are affected. For now, I downgraded to 0.28.6 until a solution is found.

na-ji avatar Aug 05 '24 10:08 na-ji

Once I put strict: true in TS config it infers properly... this might be another type of issue that you get when dealing with null types on a codebase that doesn't care about nulls... I'm lucky the codebase is small and I can enable strict stuff, others might not be 😞

Grohden avatar Aug 08 '24 12:08 Grohden

It looks like a problem with excluding generated columns without strictNullChecks.

https://github.com/drizzle-team/drizzle-orm/blob/main/drizzle-orm/src/operations.ts#L11

dbakowski avatar Aug 08 '24 16:08 dbakowski

@Grohden even with strict: true, I have the same problem.

xegulon avatar Aug 10 '24 05:08 xegulon

@xegulon did you try strict + strictNullChecks?

Grohden avatar Aug 17 '24 19:08 Grohden

is there any solution for this issue?

kkan0615 avatar Aug 18 '24 01:08 kkan0615

@Grohden yes I tried, same problem

@xegulon did you try strict + strictNullChecks?

xegulon avatar Aug 20 '24 07:08 xegulon

I am having the same issue as well

ghoshsanjoy78 avatar Aug 23 '24 06:08 ghoshsanjoy78

Same here. Nullable columns aren't shown with $inferInsert. When changing strict to true in tsconfig.json it works, but shows weird errors in other places.

rehaldinho64 avatar Aug 23 '24 16:08 rehaldinho64

@AndriiSherman @Angelelz The issue affecting $inferSelect looks to be the evaluation of the OptionalKeyOnly type.

It looks to me like the discriminator evaluating the GeneratedType type (recent addition) is expecting to find T['_']['generated']['type'] as the constant type byDefault a lot more than it is.

For me, I'm consistently seeing the T['_']['generated']['type'] as 'always' | 'byDefault'.

This is the code: https://github.com/drizzle-team/drizzle-orm/blob/90c4788980ab56c52da8504ef4fad9159c4113b0/drizzle-orm/src/operations.ts#L16-L22

I've modified part of the test from

T['_']['generated']['type'] extends 'byDefault' ? TKey : never

to

T['_']['generated']['type'] extends 'always' ? never: TKey

This seems to be a workable workaround (for me) but I've not attempted to examine the broader "generated type" code. Your expertise would be appreciated.

danielsharvey avatar Aug 25 '24 08:08 danielsharvey

@Grohden I retried with strictNullChecks true, and I do not have the problem anymore, please excuse the first message that contradicts this.

@AndriiSherman I do not know if keeping this issue is relevant anymore, because I personally do not have the problem but some still seem to have it

xegulon avatar Aug 28 '24 07:08 xegulon

Adding strictNullChecks true works for me too

lucaoskaique avatar Sep 06 '24 17:09 lucaoskaique

@AndriiSherman Is strictNullChecks a requirement for Drizzle?

danielsharvey avatar Sep 08 '24 09:09 danielsharvey

strictNullChecks fixes the type issue but breaks a lot of other code for me. I would be extremely happy about a fix for this. @danielsharvey got a very good finding for this.

icereed avatar Sep 11 '24 14:09 icereed

Quite sure this is related: https://github.com/drizzle-team/drizzle-orm/issues/2694

icereed avatar Sep 11 '24 14:09 icereed

I'm having this issue and then some:

  • $inferInsert only provides fields that are notNull() or generated by default
  • $inferSelect does not respect nullability of fields and the type has every field as required

Also on 0.32.0 orm & 0.23.0 kit

Only God knows why $inferSelect isn't the type used in the update function

I'm having issues updating a table that has a default value enum and running into type errors even after trying both with notNull() and without.

okilonet1 avatar Oct 03 '24 17:10 okilonet1

just launching the idea for who might be thinking on fixing drizzle to not care about nulls depending on the flag:

type IsStrictNullEnabled = null extends number ? false : true

const a: IsStrictNullEnabled = true // will complain depending on the flag

ts will basically treat null as any when strict null is off, so you can just ask if null extends anything non any and if it it does, the flag is off

Grohden avatar Oct 03 '24 17:10 Grohden

This also references bug #2694, which is a result of this bug I believe. This bug exists on version 0.36.1.

jeremy-returned avatar Nov 11 '24 18:11 jeremy-returned