samchon / typia

Super-fast/easy runtime validations and serializations through transformation
https://typia.io/
MIT License
4.31k stars 148 forks source link

Add the interface name in the `TypeGuardError` #1055

Open vabatta opened 2 months ago

vabatta commented 2 months ago

Description

When a typia.assert<T>() throws the TypeGuardError, would be nice to have the original T name interface as part of the Error object thrown so that it can be used to connect which interface has thrown.

Example

From the doc:

import typia, { tags } from "typia";
import { v4 } from "uuid";

typia.assert<IMember>({
  id: v4(),
  email: "samchon.github@gmail.com",
  age: 18, // wrong, must be greater than 19
});

interface IMember {
  id: string & tags.Format<"uuid">;
  email: string & tags.Format<"email">;
  age: number &
    tags.Type<"uint32"> &
    tags.ExclusiveMinimum<19> &
    tags.Maximum<100>;
}

Would throw

method: typia.assert()
path: input.age
+ interface: IMember
value: 18,
expected: number & ExclusiveMinimum<19>

Or with a change in the API

method: typia.assert()
+ path: IMember.age
value: 18,
expected: number & ExclusiveMinimum<19>
samchon commented 1 month ago

Tested, but not working due to no actual property of T type exists.

class TypeGuardError<T = any> extends Error {
  public readonly method!: string;
  public readonly path!: string | undefined;
  public readonly expected!: string;
  public readonly value!: any;
}
let s: TypeGuardError<string> = null!;
let n: TypeGuardError<number> = null!;

// NO PROBLEM
s = n;
n = s;

https://typia.io/playground/?script=MYGwhgzhAEAqCeAHApgcQK5gE4BMCiWWA9lgDyzQC80YAdvAHzTIAeALsrTjAcVtAG8AUNGiJ0AIxABLYNCzIwOIrRDxoAW2RsAFkRwBCAFzQIbLNNoBzANwixkmXIVKVasWF3HT5y1egAPtDoXMgAZpbIOHai4lKy8orKquqsKMAchiZmFtYxDvHOSW7qAG5gIOjI3nTwdgC+QiDapiYIKBjY+IQkpDl+TNS06CAgBnbNbNC0bUhomLi8vcMaEshYg9MjY3ZCMEN2tFSmNkA

samchon commented 1 month ago

To make it work, I have to make a fake property like below.

But cannot sure this is the right way.

class TypeGuardError<T = any> extends Error {
  public readonly method!: string;
  public readonly path!: string | undefined;
  public readonly expected!: string;
  public readonly value!: any;
  protected readonly fake_expected_value_?: T;
}
let s: TypeGuardError<string> = null!;
let n: TypeGuardError<number> = null!;

// COMPILE ERROR
s = n;
n = s;

https://typia.io/playground/?script=MYGwhgzhAEAqCeAHApgcQK5gE4BMCiWWA9lgDyzQC80YAdvAHzTIAeALsrTjAcVtAG8AUNGiJ0AIxABLYNCzIwOIrRDxoAW2RsAFkRwBCAFzQIbLNNoBzANwixkmXIVKVasWF3HT5y1egAPtDoXMgAZpbIOHai4lKy8orKquqsKMAchiZmFtYxDvHOSW7qAG5gIOjI3nTw+YjEHBlRia4p0GFgANbIAPppyM04veWVfQD8JrB2AL5CINqmU0homLi8JKQ5fkzUtOggIAZ2C2zQtMsoGNj4hJv7GhLIWLvnB0d2QjB7drRUpjYgA