Skip to content

feat(validator): Add type validator constraint#173

Merged
imdhemy merged 29 commits into
koala-ts:2.xfrom
EmanFateen:add-type-validator
May 17, 2026
Merged

feat(validator): Add type validator constraint#173
imdhemy merged 29 commits into
koala-ts:2.xfrom
EmanFateen:add-type-validator

Conversation

@EmanFateen
Copy link
Copy Markdown
Contributor

@EmanFateen EmanFateen commented May 11, 2026

Overview

In this PR, I have introduced new validation constraint called type.

type TypeOptions = ConstraintOptions & {
  type: AllowedTypes | AllowedTypes[];
  message?: string;
};
export type AllowedTypes =
  | 'string'
  | 'number'
  | 'boolean'
  | 'bigint'
  | 'symbol'
  | 'function'
  | 'object'
  | 'array'
  | 'null';

It's exposed through the builtInConstraints and can be used like

const rules = {
  age: [{ type: { type: 'number' } }],
  identifier: [{ type: { type: ['string', 'number'] } }],
}
  • Main purpose of this constraint is to validate whether the given value matches the expected type or one of the expected types.
  • This constraint is concerned about the type of the given value and should work as a required constraint, which means is the value is undefined the constraint will return no violations.
  • Last point doesn't applied for the null as null is a real value.

Changes made:

  1. Added the type constraint under basic constraint.
  2. Covered the required cases in type.test file.
  3. Exposed the type constraint through the builtInConstraints object.
Q A
License GPLv3
Issue Closes #169 >

@EmanFateen EmanFateen requested a review from imdhemy as a code owner May 11, 2026 12:05
@EmanFateen EmanFateen marked this pull request as draft May 11, 2026 12:06
@EmanFateen EmanFateen marked this pull request as ready for review May 11, 2026 12:34
@EmanFateen EmanFateen force-pushed the add-type-validator branch from 20516cd to 7da7d2c Compare May 14, 2026 17:31
Copy link
Copy Markdown
Member

@imdhemy imdhemy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR introduces regression to the validator component’s structure. We’ve already improved the structure in #175. Could you kindly modify the changes here to align with the updated structure? @EmanFateen

I was reviewing an older version of the PR.

Copy link
Copy Markdown
Member

@imdhemy imdhemy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EmanFateen
Thanks for moving this forward. The implementation is good and covers the issue, we just need to tighten the types and simplify the implementation.

Comment thread src/validator/constraints/basic/type.test.ts Outdated
Comment thread src/validator/constraints/basic/type.ts Outdated
Comment thread src/validator/constraints/basic/type.ts Outdated
};

export function type(value: unknown, context: ConstraintContext<TypeOptions>): Violation[] {
if (value === undefined) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case is already covered in the test cases, but it’s better to have a separate test case for it, similar to how we did for the email constraint. This approach clearly communicates the intended behavior.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A single test case with a clear intention is sufficient. For example, “it should bypass undefined value.”

You’ve added two test cases with different descriptions of behavior.

https://github.com/EmanFateen/framework/blob/d120ee5c1b643da1101e7b399e83b0ab1a726837/src/validator/constraints/basic/type.test.ts#L64

https://github.com/EmanFateen/framework/blob/d120ee5c1b643da1101e7b399e83b0ab1a726837/src/validator/constraints/basic/type.test.ts#L115

Copy link
Copy Markdown
Contributor Author

@EmanFateen EmanFateen May 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept returns no violations for undefined value and removed the redundant one.
I see returns no violations for undefined value more clear than “it should bypass undefined value.”

Done

Comment thread src/validator/constraints/basic/type.ts Outdated
Comment thread src/validator/constraints/basic/type.ts Outdated
Comment thread src/validator/constraints/basic/type.ts Outdated
Comment thread src/validator/constraints/basic/type.ts Outdated
Comment thread src/validator/constraints/basic/type.ts Outdated
Comment thread src/validator/constraints/basic/type.ts Outdated
Comment thread src/validator/constraints/basic/type.ts Outdated
}

function getDefaultMessageWith(types: AllowedTypes[]): string {
if (Array.isArray(types) && types.length > 1) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you’ve already declared types as an array, there’s no need to perform the check.

Comment thread src/validator/constraints/basic/type.ts Outdated
Comment thread src/validator/constraints/basic/type.ts Outdated
Comment thread src/validator/constraints/basic/type.ts Outdated
};

export function type(value: unknown, context: ConstraintContext<TypeOptions>): Violation[] {
if (value === undefined) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A single test case with a clear intention is sufficient. For example, “it should bypass undefined value.”

You’ve added two test cases with different descriptions of behavior.

https://github.com/EmanFateen/framework/blob/d120ee5c1b643da1101e7b399e83b0ab1a726837/src/validator/constraints/basic/type.test.ts#L64

https://github.com/EmanFateen/framework/blob/d120ee5c1b643da1101e7b399e83b0ab1a726837/src/validator/constraints/basic/type.test.ts#L115

@imdhemy imdhemy changed the title feat(Validation): Add type validator constraint feat(validator): Add type validator constraint May 17, 2026
Copy link
Copy Markdown
Member

@imdhemy imdhemy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EmanFateen
Thank you!

I made ConstraintOptions generic so generic schema code can stay flexible, while specific constraints can keep precise option shapes. The old index signature leaked into every constraint-specific options type; now only the default generic form is loose, and ConstraintOptions<{ ... }> keeps custom constraint options strict while still sharing groups.

@imdhemy imdhemy merged commit 4aac95d into koala-ts:2.x May 17, 2026
1 check passed
EmanFateen added a commit to EmanFateen/framework that referenced this pull request May 18, 2026
* feat: add passing type constraint

* chore: cover type constraint violation

* chore: support matching type constraint values

* chore: support type constraint alternatives

* chore: allow optional type constraint values

* chore: support type constraint custom message

* chore: format type constraint alternatives

* chore: register type constraint

# Conflicts:
#	src/validator/constraints/index.ts

* chore: fix code style

* chore: use TypeOptions due to rebase

* Simplify type constraint message formatting

* chore: add separate test case for the undefined values.

* chore: refactor getDefaultMessageWith method.

* chore: add a list of AllowedTypes types

* chore: code format

* chore: remove redundant test case

* chore: remove redundant check

* chore: fix AllowedTypes

* chore: inline options

* chore: rename test case

* chore: use one default message

* chore: inline method

* chore: rename AllowedType

* chore: refactor  normalizedTypes

* chore: remove the undefined type case from each

* chore(validator): make constraint options generic

* chore: align type constraint options

* chore: code refactoring

* chore: fix type mismatch

---------

Co-authored-by: Dhemy <imdhemy@gmail.com>
EmanFateen added a commit to EmanFateen/framework that referenced this pull request May 18, 2026
* feat: add passing type constraint

* chore: cover type constraint violation

* chore: support matching type constraint values

* chore: support type constraint alternatives

* chore: allow optional type constraint values

* chore: support type constraint custom message

* chore: format type constraint alternatives

* chore: register type constraint

# Conflicts:
#	src/validator/constraints/index.ts

* chore: fix code style

* chore: use TypeOptions due to rebase

* Simplify type constraint message formatting

* chore: add separate test case for the undefined values.

* chore: refactor getDefaultMessageWith method.

* chore: add a list of AllowedTypes types

* chore: code format

* chore: remove redundant test case

* chore: remove redundant check

* chore: fix AllowedTypes

* chore: inline options

* chore: rename test case

* chore: use one default message

* chore: inline method

* chore: rename AllowedType

* chore: refactor  normalizedTypes

* chore: remove the undefined type case from each

* chore(validator): make constraint options generic

* chore: align type constraint options

* chore: code refactoring

* chore: fix type mismatch

---------

Co-authored-by: Dhemy <imdhemy@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[validator] Add built-in type basic validator constraint

2 participants