typia icon indicating copy to clipboard operation
typia copied to clipboard

Error when validating Prisma.JsonValue

Open ninthsun91 opened this issue 7 months ago • 2 comments

Issue with Prisma.JsonValue

Prisma has a JsonValue type, which is defined as below.

export declare type JsonValue = string | number | boolean | JsonObject | JsonArray | null;
export declare type JsonObject = {
    [Key in string]?: JsonValue;
};
export declare interface JsonArray extends Array<JsonValue> {}

Following to above definition, an array with primitive values still conforms to JsonValue. So, arrays like [1, 2, 3], ['hello', 'world'] or [1, 'hello', true] are all valid JsonValue.

However, typia throws an error like this.

typia.validate<JsonArray>([1, 2, 3]);
{
  success: false,
  errors: [
    {
      path: '$input',
      expected: '(JsonArray | JsonObject | boolean | null | number | string)',
      value: [Array]
    }
  ],
  data: undefined
}

This is very weird, because when you make the same type as a type alias, this one passes like this.

type TJsonArray = Array<JsonValue>;
typia.validate<TJsonArray>([1, 2, 3]);

// or this also works
// typia.validate<Array<JsonValue>>([1, 2, 3]);

{ success: true, errors: [], data: [ 1, 2, 3 ] }

type TJsonArray = Array<JsonValue>; and interface IJsonArray extends Array<JsonValue> {} should be the same as long as I understand, and other library such as zod doesn't have the same issue. ~~Or my zod implementation might be wrong.~~

So, it seems the way how typia uses interface and type alias is causing the issue.

Reproduction

I made a small reproduction project here.

change the DATABASE_URL in .env to yours, and run

$ pnpm install
$ pnpm migrate
$ pnpm dev

to start the project.

Then console will print things like this

[Nest] 75843  - 11/13/2023, 10:53:13 PM     LOG [NestFactory] Starting Nest application...
[Nest] 75843  - 11/13/2023, 10:53:13 PM     LOG [InstanceLoader] PrismaModule dependencies initialized +299ms
[Nest] 75843  - 11/13/2023, 10:53:13 PM     LOG [InstanceLoader] AppModule dependencies initialized +2ms
zod:: { success: true, data: [ 1, 'two', null ] }
typia:: {
  success: false,
  errors: [
    {
      path: '$input',
      expected: '(JsonArray | JsonObject | boolean | null | number | string)',
      value: [Array]
    }
  ],
  data: undefined
}
Array<JsonValue>:: { success: true, errors: [], data: [ 1, 'two', null ] }
[Nest] 75843  - 11/13/2023, 10:53:13 PM     LOG [InstanceLoader] UsersModule dependencies initialized +3ms
[Nest] 75843  - 11/13/2023, 10:53:13 PM     LOG [RoutesResolver] AppController {/}: +30ms
[Nest] 75843  - 11/13/2023, 10:53:13 PM     LOG [RouterExplorer] Mapped {/, GET} route +2ms
[Nest] 75843  - 11/13/2023, 10:53:13 PM     LOG [RoutesResolver] UsersController {/users}: +0ms
[Nest] 75843  - 11/13/2023, 10:53:13 PM     LOG [RouterExplorer] Mapped {/users, POST} route +0ms
[Nest] 75843  - 11/13/2023, 10:53:13 PM     LOG [RouterExplorer] Mapped {/users/:id, GET} route +0ms
[Nest] 75843  - 11/13/2023, 10:53:13 PM   DEBUG [PrismaService] Prisma connected
[Nest] 75843  - 11/13/2023, 10:53:13 PM     LOG [NestApplication] Nest application successfully started +1ms

some example codes with validating is in src/users/users.controller.ts.

about database connection and schema

It requires PostgreSQL because I want to ensure that Prisma and PostgreSQL does not take this as an issue. It's only typia related validations saying an array is not a valid JsonValue.

You can find this when sending an api request to POST /users. It will create a data in the database, but will throw validation error while serializing response body with Nestia.

Also, it doesn't look like pnpm issue related to node_modules structure. I tried with npm, or hoisted pnpm but it was the same.

ninthsun91 avatar Nov 13 '23 14:11 ninthsun91

Your type definition is invalid.

The JsonValue must be defined like below.

type JsonValue = string | number | boolean | JsonObject | JsonArray | null;
type JsonObject = {
    [Key in string]?: JsonValue;
};
type JsonArray = Array<JsonValue>;

At first, you've not to extends the Array type through the interface (interface JsonArray extends Array<JsonValue>.

The definition means that JsonArray is not an Array type, but an Object type which has length: number property and [n: number]: T accessor. Therefore, it would be considered to not Array, but some ArrayLike Object type. The reason why typia had reported you that [1, 2, 3] is invalid type also base on the fact. It's not a bug, but exactly spec.

If you define the JsonArray like above, then there will not be any problem.

samchon avatar Nov 13 '23 15:11 samchon

I found that Prisma actually defined JsonArray type to extending the Array.

It is bug of Prisma, so I'll report issue about that.

samchon avatar Nov 13 '23 15:11 samchon

Prisma issue had been delayed too much time.

Therefore, I did hard coded for this case.

Now, upgrade to v5.5.5, then be supported.

samchon avatar Mar 14 '24 07:03 samchon