Skip to content

fix: type the validated value as unknown - #243

Closed
alexander-akait wants to merge 2 commits into
mainfrom
fix/validate-unknown-options
Closed

alexander-akait wants to merge 2 commits into
mainfrom
fix/validate-unknown-options

Conversation

@alexander-akait

@alexander-akait alexander-akait commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Summary

A validator checks a value whose type isn't known yet, but validate declared it as object[] | object and a precompiled check took any. Callers had to cast their input to object before validating it. In webpack, that cast is one of the escape hatches its type coverage counts (webpack/webpack#23047).

export function validate(schema: Schema, options: object[] | object, …): void; // before
export function validate(schema: Schema, options: unknown, …): void;           // after

export type PrecompiledCheck = (value: EXPECTED_ANY) => boolean; // before
export type PrecompiledCheck = (value: unknown) => boolean;      // after

The runtime is unchanged. validate already handles an array and any other value through Array.isArray, and the schema decides what is valid.

What kind of change does this PR introduce?

fix

Did you add tests for your changes?

No; only the declared types change. All 1046 existing tests pass, and npm run lint passes. The declarations were regenerated with npm run build:types.

Does this PR introduce a breaking change?

No. The parameter now accepts anything it accepted before, and a precompiled check typed (value: unknown) => boolean is still callable with any value.

If relevant, what needs to be documented once your changes are merged or what have you already documented?

n/a

Use of AI

Claude Code found the cast while reducing escape hatches in webpack, wrote the change, and checked it with npm run lint, the test suite and the regenerated declarations. The author reviewed it.


Generated by Claude Code

Summary by CodeRabbit

  • TypeScript
    • The validate options parameter is now typed as unknown, replacing the previous object-or-array type. This broadens the values accepted by the public type declaration; runtime behavior is unchanged.
  • Documentation
    • Clarified that validation options may be provided as an object or an array of objects.

A validator checks a value of a type not yet known, so `validate`'s
options and a precompiled check's value are `unknown` rather than
`object | object[]` and `any`. Callers no longer cast to `object`
before validating.
@codecov

codecov Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.23%. Comparing base (2d6aaec) to head (7ea2e68).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #243   +/-   ##
=======================================
  Coverage   97.23%   97.23%           
=======================================
  Files          13       13           
  Lines        1231     1231           
  Branches      476      476           
=======================================
  Hits         1197     1197           
  Misses         32       32           
  Partials        2        2           
Flag Coverage Δ
integration 97.23% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai

coderabbitai Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b0701f85-e390-48c8-8157-74f43254acee
Commits

Reviewing files that changed from the base of the PR and between 79ff326 and 7ea2e68.

Files selected for processing: 3
  • .changeset/validate-unknown-options.md
  • declarations/validate.d.ts
  • src/validate.js
Files skipped from review as they are similar to previous changes: 1
  • .changeset/validate-unknown-options.md

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 0 remain after this review.

Walkthrough

The validate declaration and source JSDoc now type the options parameter as unknown. The JSDoc describes options as an object or an array of objects. A changeset records a patch release for schema-utils.

Merge Risk: Minimal · up to 7ea2e

The type-only API change introduces no identified current-head risk and is ready to merge.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title refers to the real type change to unknown, but it calls the parameter the “validated value” instead of the validate options parameter. It is still related to the main change.
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 2 functions across 2 files. (1 skipped: 1 unsupported.)

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2


Review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f466fd2c-cdfd-430c-be01-c8ec5320de56
Commits

Reviewing files that changed from the base of the PR and between 2d6aaec and 79ff326.

Files selected for processing: 3
  • .changeset/validate-unknown-options.md
  • declarations/validate.d.ts
  • src/validate.js

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

Comment thread .changeset/validate-unknown-options.md Resolved
Comment thread declarations/validate.d.ts Resolved
A check a caller types by its own options, `(value: MyOptions) => boolean`,
is not assignable to `(value: unknown) => boolean`, so keep the value `any`
there. Only `validate`'s options become `unknown`, which accepts every
value it did.

Copy link
Copy Markdown
Member Author

Closing: neither form is worth it.

  • options: unknown fixes nothing in schema-utils. It also drops the type-level hint that validate takes an options object or an array of them.
  • A generic (validate<T extends object | object[]>(…, options: T, …, check?: PrecompiledCheck<T>)) was checked with tsc. It breaks a call that compiles today: options typed object with a check typed by the caller's options fails, because T is inferred as MyOptions. It also doesn't let webpack drop its cast, since an unconstrained T still isn't assignable to object | object[].

So object | object[] is the real type of this API, and webpack keeps its cast as a real one.


Generated by Claude Code

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.

1 participant