Skip to content

Fix "Return types are not inferred in standard mode"#758

Merged
yamcodes merged 12 commits intomainfrom
return-types-are-not-inferred-in-standard-mode
Jan 21, 2026
Merged

Fix "Return types are not inferred in standard mode"#758
yamcodes merged 12 commits intomainfrom
return-types-are-not-inferred-in-standard-mode

Conversation

@yamcodes
Copy link
Owner

@yamcodes yamcodes commented Jan 21, 2026

Summary by CodeRabbit

  • New Features

    • Added explicit Standard validator mode for environment schemas so inferred types match the chosen validator.
  • Documentation

    • Added design, spec, and proposal docs clarifying validator modes and inference rules.
  • Tests

    • Added comprehensive type-level and runtime tests for Standard Mode, error cases, and mixed scenarios.
  • Chores

    • Adjusted type handling in integrations to accommodate overloads and improved validator option typing.

✏️ Tip: You can customize this high-level summary in your review settings.

@yamcodes yamcodes added the bug Something isn't working label Jan 21, 2026
@changeset-bot
Copy link

changeset-bot bot commented Jan 21, 2026

🦋 Changeset detected

Latest commit: acbed78

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
arkenv Patch
@arkenv/bun-plugin Patch
@arkenv/vite-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@yamcodes yamcodes added the @arkenv/vite-plugin Issues or Pull Requests involving the Vite plugin for ArkEnv label Jan 21, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 21, 2026

Warning

Rate limit exceeded

@yamcodes has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 15 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

Implements Standard Mode type inference for createEnv by adding a dedicated overload for validator: "standard", refining ArkEnvConfig validator literals, updating createEnv overload ordering/returns, adding specs/docs/tasks, and tests; small caller-side type-workarounds updated in plugin helpers.

Changes

Cohort / File(s) Summary
Documentation & Specs
openspec/changes/fix-standard-mode-inference/design.md, openspec/changes/fix-standard-mode-inference/proposal.md, openspec/changes/fix-standard-mode-inference/specs/inference/spec.md, openspec/changes/fix-standard-mode-inference/tasks.md, openspec/specs/validator-mode/spec.md
Adds design, proposal, formal spec, and tasks clarifying Standard vs ArkType validator modes and the expected type-inference behavior for createEnv.
Core: create-env implementation
packages/arkenv/src/create-env.ts
Introduces a createEnv overload for const T extends Record<string, StandardSchemaV1> with config: ArkEnvConfig & { validator: "standard" } returning { [K in keyof T]: StandardSchemaV1.InferOutput<T[K]> }; refactors other overloads (arktype/default path), adjusts overload ordering, updates imports to include StandardSchemaV1, and simplifies the standard-path return cast.
Tests
packages/arkenv/src/standard-mode.test.ts
New test suite validating Standard Mode type inference and runtime expectations with mocked Standard Schema validators and type-level assertions.
Plugin callers / type-workarounds
packages/bun-plugin/src/utils.ts, packages/vite-plugin/src/index.ts
Replace generic-typed createEnv<T> calls with options as any casts and updated comments to avoid overload mismatch; no runtime logic changes.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰
Overloads bloom where validators meet,
I hop through types with nimble feet,
Standard maps and ArkType skies,
I infer your vars with joyful eyes,
A tiny hop — your types complete.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly addresses the main bug fix: implementing proper type inference for Standard Mode in createEnv, which is the primary objective across all documentation and implementation changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added docs Improvements or additions to documentation and removed @arkenv/vite-plugin Issues or Pull Requests involving the Vite plugin for ArkEnv labels Jan 21, 2026
- Add new overload for standard schemas
- Explicitly type arktype validator config
- Remove ambiguous general overload
@github-actions github-actions bot added the arkenv Changes to the `arkenv` npm package. label Jan 21, 2026
@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 21, 2026

Open in StackBlitz

npm i https://pkg.pr.new/arkenv@758
npm i https://pkg.pr.new/@arkenv/bun-plugin@758
npm i https://pkg.pr.new/@arkenv/vite-plugin@758

commit: acbed78

@arkenv-bot
Copy link
Contributor

arkenv-bot bot commented Jan 21, 2026

📦 Bundle Size Report

Package Size Limit Diff Status
@arkenv/vite-plugin 1.55 kB 1.95 kB 0.0%
arkenv 1.38 kB 2.93 kB 0.0%
@arkenv/bun-plugin 2.01 kB 2.44 kB 0.0%

All size limits passed!

- Update createEnv return cast for standard mode
- Add comprehensive tests for standard mode inference
- Ensure correct type inference for various schemas
@github-actions github-actions bot added the tests This issue or PR is about adding, removing or changing tests label Jan 21, 2026
@yamcodes yamcodes marked this pull request as ready for review January 21, 2026 16:47
- Mark validation tasks as complete
- Refine type assertions in standard mode tests
- Update test type error suppression
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@openspec/changes/fix-standard-mode-inference/specs/inference/spec.md`:
- Line 11: Fix the capitalization in the assertion sentence by changing the word
"Have" to lowercase "have" in the sentence "**THEN** the returned object MUST
Have types exactly matching the Zod output types" so it reads "**THEN** the
returned object MUST have types exactly matching the Zod output types"; update
that exact line in the spec (the sentence containing "MUST Have") to maintain
grammatical consistency.
🧹 Nitpick comments (7)
openspec/changes/fix-standard-mode-inference/specs/inference/spec.md (1)

14-16: Add missing GIVEN clause for consistency with scenario format.

The second scenario lacks a GIVEN clause, which breaks the pattern established by the first scenario and the coding guidelines that specify using WHEN and THEN bullet points. Consider adding a GIVEN clause for completeness.

Suggested improvement
 #### Scenario: Inferred types are usable without ArkType
+- **GIVEN** a user consuming ArkEnv with Standard Schema validators
 - **GIVEN** `validator: "standard"` is used
-- **THEN** types of the returned environment object MUST NOT depend on ArkType types at the consumer level
+- **WHEN** the environment object is accessed
+- **THEN** its types MUST NOT depend on ArkType types at the consumer level
openspec/changes/fix-standard-mode-inference/design.md (1)

61-61: Minor: Hyphenate "ArkType-based" for grammatical correctness.

Per standard grammar conventions, compound adjectives before a noun should be hyphenated.

Suggested fix
-Actually, the user said: "it obviously happens because the return types of createEnv are all arktype based, but in recent changes we've made it so that arktype is not required anymore."
+Actually, the user said: "it obviously happens because the return types of createEnv are all ArkType-based, but in recent changes we've made it so that arktype is not required anymore."
openspec/changes/fix-standard-mode-inference/proposal.md (1)

19-30: Add Impact section per coding guidelines.

The proposal template should include an Impact section. Even if the impact is minimal (since this is primarily a type-level fix with no runtime changes), it's good to document this explicitly.

Suggested addition
 ## Explicit Non-Goals
 - Changing the runtime validation logic (already implemented).
 - Introducing complex auto-detection of schemas (we stick to the explicit `validator` flag).
+
+## Impact
+- **Type-level only**: This change affects TypeScript inference but does not modify runtime behavior.
+- **Non-breaking**: Existing code using ArkType mode (default) continues to work unchanged.
+- **Standard mode users**: Will now get correct type inference matching their validator's output types (e.g., Zod, Valibot).

 ## Design Principle

As per coding guidelines, proposal.md files should include an Impact section.

packages/arkenv/src/standard-mode.test.ts (2)

14-40: Consider using afterEach for environment cleanup.

Currently, vi.unstubAllEnvs() is called at the end of each test. If a test fails or throws before reaching the cleanup line, the stubbed environment may leak into subsequent tests. Moving cleanup to afterEach ensures consistent cleanup regardless of test outcome.

Suggested refactor
 describe("Standard Mode Type Inference", () => {
+	afterEach(() => {
+		vi.unstubAllEnvs();
+	});
+
 	it("should infer correct types from Standard Schema validators", () => {
 		vi.stubEnv("STRING_VAR", "test");
 		vi.stubEnv("NUMBER_VAR", "42");
 		vi.stubEnv("BOOLEAN_VAR", "true");
 		// ... test body ...
-		vi.unstubAllEnvs();
 	});

Apply the same pattern to all tests in the file.

As per coding guidelines: "Use beforeEach/afterEach for cleanup, not beforeAll/afterAll when possible."


102-123: Consider adding runtime value assertions for completeness.

This test validates type-level correctness but doesn't assert the runtime values. While the type assertions are the primary goal, adding runtime assertions would make the test more comprehensive.

Suggested addition
 		expectTypeOf(env).toEqualTypeOf<{
 			VAR1: string;
 			VAR2: number;
 			VAR3: { nested: string };
 		}>();

+		// Runtime assertions
+		expect(env.VAR1).toBe("string-output");
+		expect(env.VAR2).toBe(999);
+		expect(env.VAR3).toEqual({ nested: "object" });
+
 		vi.unstubAllEnvs();
 	});
packages/arkenv/src/create-env.ts (2)

92-95: Consider narrowing standard-mode config to prevent unsupported options.

Standard mode ignores coerce and arrayFormat, but ArkEnvConfig still allows them (and defaults coerce to true). A dedicated config type avoids misleading call sites.

♻️ Suggested type tightening
+type StandardModeConfig = Omit<ArkEnvConfig, "coerce" | "arrayFormat" | "validator"> & {
+	validator: "standard";
+	coerce?: false;
+	arrayFormat?: never;
+};
+
 export function createEnv<const T extends Record<string, StandardSchemaV1>>(
 	def: T,
-	config: ArkEnvConfig & { validator: "standard" },
+	config: StandardModeConfig,
 ): { [K in keyof T]: StandardSchemaV1.InferOutput<T[K]> };

153-153: Optional: avoid as any in the standard path.

A small typed wrapper keeps local type safety without widening the return to any.

♻️ Possible refactor
+function parseStandardTyped<const T extends Record<string, StandardSchemaV1>>(
+	def: T,
+	config: ArkEnvConfig,
+): { [K in keyof T]: StandardSchemaV1.InferOutput<T[K]> } {
+	return parseStandard(def as Record<string, unknown>, config) as {
+		[K in keyof T]: StandardSchemaV1.InferOutput<T[K]>;
+	};
+}
+
 	if (mode === "standard") {
@@
-		return parseStandard(def as Record<string, unknown>, config) as any;
+		return parseStandardTyped(def as Record<string, StandardSchemaV1>, config);
 	}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@openspec/changes/fix-standard-mode-inference/tasks.md`:
- Around line 2-12: The tasks.md checklist currently uses checked items ("-
[x]") which violates the guideline; update all checklist entries in
openspec/changes/fix-standard-mode-inference/tasks.md to use unchecked items ("-
[ ]") instead (replace every "- [x]" with "- [ ]"), ensuring entries such as
"1.1", "2.1"–"2.3", and "3.1"–"3.3" are converted so the file follows the
required unchecked checklist format.

- Use `as any` for createEnv calls
- Resolve union type overload issues
- Simplify ArkEnvConfig definition
@github-actions github-actions bot added the @arkenv/vite-plugin Issues or Pull Requests involving the Vite plugin for ArkEnv label Jan 21, 2026
- Correctly infers types from Standard Schema validators
- Avoids wrapping types in ArkType-specific wrappers
@yamcodes yamcodes merged commit 3b747b0 into main Jan 21, 2026
18 checks passed
@yamcodes yamcodes deleted the return-types-are-not-inferred-in-standard-mode branch January 21, 2026 17:15
@arkenv-bot arkenv-bot bot mentioned this pull request Jan 21, 2026
@arkenv-bot
Copy link
Contributor

arkenv-bot bot commented Jan 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (Asia/Almaty)
arkenv Ready Ready Preview, Comment Jan 21 2026, 10:18 PM (Asia/Almaty)

yamcodes pushed a commit that referenced this pull request Jan 21, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## arkenv@0.9.1

### Patch Changes

- #### Fix Standard Schema type inference
_[`#758`](#758)
[`3b747b0`](3b747b0)
[@yamcodes](https://github.com/yamcodes)_

Fixed type inference when using `validator: "standard"` mode. The `env`
object now correctly infers types from Standard Schema validators like
Zod or Valibot.

## @arkenv/bun-plugin@0.1.1

### Patch Changes

- #### Support configuration
_[`#763`](#763)
[`06de0ef`](06de0ef)
[@yamcodes](https://github.com/yamcodes)_

Add support for an optional configuration object as the second argument.
This allows you to set the `validator` mode to `"standard"`, enabling
support for libraries like Zod or Valibot without an ArkType dependency.

    ```ts
    import { z } from "zod";
    import arkenv from "@arkenv/bun-plugin";

    arkenv(
      {
        BUN_PUBLIC_API_URL: z.string().url(),
      },
      {
        validator: "standard",
      }
    );
    ```

<details><summary>Updated 1 dependency</summary>

<small>


[`3b747b0`](3b747b0)

</small>

-   `arkenv@0.9.1`

</details>

## @arkenv/vite-plugin@0.0.28

### Patch Changes

- #### Support configuration
_[`bb832b1`](bb832b1)
[@yamcodes](https://github.com/yamcodes)_

Add support for an optional configuration object as the second argument.
This allows you to set the `validator` mode to `"standard"`, enabling
support for libraries like Zod or Valibot without an ArkType dependency.

    ```ts
    import { z } from "zod";
    import arkenvVitePlugin from "@arkenv/vite-plugin";

    arkenvVitePlugin(
      {
        VITE_API_URL: z.string().url(),
      },
      {
        validator: "standard",
      }
    );
    ```

<details><summary>Updated 1 dependency</summary>

<small>


[`3b747b0`](3b747b0)

</small>

-   `arkenv@0.9.1`

</details>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
yamcodes added a commit that referenced this pull request Feb 10, 2026
## Summary

- Reorder `createEnv` overloads so the inline `EnvSchema<T>` overload is
evaluated first, restoring ArkType DSL string autocomplete
- Narrow the `config` parameter on ArkType-specific overloads to `{
validator?: "arktype" }` so they don't greedily match `{ validator:
"standard" }` calls — preserving correct return type inference for
standard mode (#758)

Closes #790

## Context

This is the same autocomplete regression originally reported in #522 and
fixed in #531 (v0.7.8). It regressed when #758 moved the
`StandardSchemaV1` overload to first position to fix standard mode
return types. The root cause was that overload ordering was the *only*
mechanism disambiguating the two modes — this fix makes the overloads
mutually exclusive via their config types, so ordering is no longer a
correctness concern.

## Test plan

- [x] All 227 arkenv tests pass (including standard mode type inference
tests with `expectTypeOf`)
- [x] Full monorepo test suite passes (6/6 projects)
- [x] Manually verified inline schema autocomplete works in editor
- [x] Manually verified standard mode return type inference works in
editor

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **Bug Fixes**
* Fixed inline schema autocompletion functionality for ArkType DSL
strings when using arkenv() with inline schema objects.

* **Refactor**
* Improved createEnv function by narrowing overloads based on validator
configuration type. Overloads are now mutually exclusive and
order-independent.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

@arkenv/vite-plugin Issues or Pull Requests involving the Vite plugin for ArkEnv arkenv Changes to the `arkenv` npm package. bug Something isn't working docs Improvements or additions to documentation tests This issue or PR is about adding, removing or changing tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant