Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type validation is not used for Record keys or indexable types #853

Closed
kade-robertson opened this issue Oct 25, 2023 · 3 comments
Closed
Assignees
Labels
bug Something isn't working

Comments

@kade-robertson
Copy link

📝 Summary

I'd like to be able to provide a type that limits a string to be of a certain format, and then re-use that type in multiple places to enforce the same formatting everywhere.

  • Typia Version: 5.2.4 & typia@next
  • Expected behavior: A type of the form type T = string & tags.Pattern<'.*'>; can be used anywhere and have the same validation applied.
  • Actual behavior: A type of the above form works when used as the property of a

It seems like this primarily applies to object keys, where some default test is applied to keys and it ignores any other tests that type should have applied to it. I assumed this was maybe due to the type being an alias of a primitive (or something like that), but the type itself works fine if used in any other instance except as the key of an object.

Notably, this validation does work for maps, but not Records or using indexable types.

This is related to #725, but my type alias is using tags to add extra conditions. I would have assumed that could work?

⏯ Playground Link

https://typia.io/playground/?script=JYWwDg9gTgLgBDAnmYBDANHA3g1BzAZzgF84AzKCEOAIiRVRoG4AoF+gUzgGEBXAmFQCSAEzgBeOAKjAAdnjgAyXIQB0ABVQwYHKLIA8AcgB6AbQAMAWgCcqSwC8AulgCMANmIASQwD5WLAHoAuAB3aABrAhYAYwhZATgAN1QAG2ARLQ5RCQRkNFVoqA5MoQJ9PgFhER8ACgBKfzkdKDJUaK4AZSoOADVU3i4sFjgRuHSALh5+QRBRVlG4LRgZACNeHUnZXhAV3VZiNiDQiKjY+PhktIydLpBe-q5JenzC4p1S-Vv7lIHahrZOHAvgB5GAAC10fR+j2ww1GEymlVmInmowg4N0AEFtKt1hxNttdlB9odgmEoJEYnEEpd0pkQRioFCBjlnqgCkUSmUGRCmQ8-v5AcyONwICkUhxojBgHEcgAlSXQETlaZVTBfYV+UlwEQQDhEWTo44UqnnJKpOk6UXiyXS2VPPLs15c-TC60SqUy2QCthNXStdpwUG8t1ij122SwhamcIcRCTCozUSOSY8yEPEmBYK6-VwQ3wcnhU00i3XDjB3Tu21e1mOjlvLJlCt86FVz1xAVAA

Comparison with Map:
https://typia.io/playground/?script=JYWwDg9gTgLgBDAnmYBDANHA3g1BzAZzgF84AzKCEOAIiRVRoG4AoF+gUzgGEBXAmFQCSAEzgBeOAKjAAdnjgAyXIQB0ABVQwYHKLIA8AcgB6AbQAMAWgCcqSwC8AulgCMANmIASQwD5WLAHoAuAB3aABrAnZkNFUAYygOLQ4hAn0AWVQwfT4BYRFMWV4QACNdHx8ACgBKfyC4EQgOIlkIeDCocOiGeMTk1P0AJQ446BEc-kEQUULisqgKmrrgxua4VvaI7tiEpJ0BrBY4Y7hTcI5EAC4eSfzHa6LS3RZiKtqgA

💻 Code occuring the bug

import typia, { tags } from "typia";

type CustomId = string & tags.Pattern<'^[0-9a-z]{16}$'>;

// works
const validateId = typia.createIs<CustomId>();

interface SomeValue {
    id: CustomId;
    attribute: number;
}

// works
const validateSomeValue = typia.createIs<SomeValue>();

type SomeOtherValue = {
    id: CustomId;
    otherAttribute: number;
}

// works
const validateSomeOtherValue = typia.createIs<SomeOtherValue>();

type ValueCollection = Record<CustomId, SomeValue>;

// does not work
const validateCollection = typia.createIs<ValueCollection>();

interface OtherValueCollection {
    [key: CustomId]: SomeOtherValue;
}

// does not work
const validateOtherCollection = typia.createIs<OtherValueCollection>();

Comparison to Map:

import typia, { tags } from "typia";

type CustomId = string & tags.Pattern<'^[0-9a-z]{16}$'>;

// works
typia.createIs<Map<CustomId, number>>();

// does not work
typia.createIs<Record<CustomId, number>>();

// does not work
typia.createIs<{
    [key: CustomId]: number
}>();
@kade-robertson
Copy link
Author

Note that this appears to happen even when I define this type without an explicitly defined alias: https://typia.io/playground/?script=JYWwDg9gTgLgBDAnmYBDANHA3g1BzAZzgF84AzKCEOAIiRVRoG4AoFgenYFoeuP24ANQCCAGQCSAEWEAVcQHkAcv1596aAHQBjKAFNUMXeIIAeAEq6t0ACYmCMKMAB2eOADJchDQAUDhqE4mAOQAegDaqFwAXgC6ACRBAHyYTgCuIABGulCJiQAUAJRMQA

import typia, { tags } from "typia";

// does not work
typia.createIs<Record<string & tags.Pattern<'^[a-z]$'>, number>>();

@samchon
Copy link
Owner

samchon commented Oct 27, 2023

Good reporting. I'll fix that bug.

@samchon samchon self-assigned this Oct 27, 2023
@samchon samchon added the bug Something isn't working label Oct 27, 2023
@samchon
Copy link
Owner

samchon commented Nov 5, 2023

Upgrade to v5.2.5, then the problem would be solved.

By the way, consider to using assertEquals() function, because assert() function allows superfluous properties.

export interface DynamicTag {
    [key: number & tags.Minimum<0> & tags.ExclusiveMaximum<10>]: bigint &
        tags.Type<"uint64">;
    [key: string & tags.Format<"uuid">]: string & tags.Format<"email">;
}

const dynamic: DynamicTag = {};
dynamic["something"] = "nothing";
typia.is<DynamicTag>(dynamic); // true
typia.equals<DynamicTag>(dynamic); // false

@samchon samchon closed this as completed in c17dc44 Nov 5, 2023
samchon added a commit that referenced this issue Nov 5, 2023
Fix #853 - `Record<string & tags.Format<"uuid">, T>` case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants