Skip to content

fix: primitive() and enum validation now correctly handle null#32

Merged
SrHenry merged 1 commit into
masterfrom
hotfix/primitive-null-validation
May 25, 2026
Merged

fix: primitive() and enum validation now correctly handle null#32
SrHenry merged 1 commit into
masterfrom
hotfix/primitive-null-validation

Conversation

@SrHenry

@SrHenry SrHenry commented May 25, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #31

The primitive() schema guard and validateDefault both used Generics.Primitives.includes(typeof arg) to check if a value is a primitive. Since typeof null === "object" (not "null"), null was never matched despite being part of the PrimitiveType union.

Changes

Root cause fix — src/validators/schema/primitive.ts

Added explicit arg === null check before the typeof check in the guard:

branchIfOptional(arg, []) || arg === null || (Generics.Primitives as readonly string[]).includes(typeof arg)

This mirrors the pattern used in asNull.ts which already checks arg === null directly.

Same structural bug in validator — src/validators/schema/helpers/validate/validateDefault.ts

The validateDefaultInner function had the same typeof-only check in two places:

  1. primitive case (line 68) — Added ctx.arg !== null && guard before the typeof check
  2. enum case (line 189) — Same fix applied. This was an additional bug with the same root cause: asEnum schemas containing null values would fail validation because the enum case in validateDefault rejects non-typeof-matchable values before checking enum members.

Note: The asEnum.ts guard itself delegates to primitive(), so it is automatically fixed by the primitive.ts change. The separate fix was only needed in validateDefault.ts.

Tests — src/validators/__tests__/primitive.spec.ts

Replaced the skipped stub with a full test suite covering:

  • All primitive types including null (the core bug)
  • Non-primitive rejection
  • optional() variant
  • validator() method existence

Reproduction (before fix)

primitive()(null)       // false — now true
primitive().optional()(null)  // false — now true

The primitive() schema guard relied on typeof checks via
Generics.Primitives.includes(typeof arg), but typeof null === 'object'
not 'null', so null was never matched despite being in PrimitiveType.

Same bug existed in validateDefault for both the primitive and enum
cases where the typeof check was used as an early rejection filter.

Fixes #31
@SrHenry SrHenry linked an issue May 25, 2026 that may be closed by this pull request
@SrHenry SrHenry merged commit d4049b2 into master May 25, 2026
5 checks passed
@SrHenry SrHenry deleted the hotfix/primitive-null-validation branch May 25, 2026 23:52
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.

bug: enum schema validation in validateDefault rejects null values bug: primitive() schema fails to validate null

1 participant