Skip to content

Conversation

@sentik
Copy link
Contributor

@sentik sentik commented Nov 4, 2025

Add TypeScript isolatedDeclarations support for Zod module

Overview

This PR adds full support for TypeScript's isolatedDeclarations compiler option in the Zod module. This ensures that generated Zod schemas and related code are compatible with TypeScript's isolated declaration files feature, which requires explicit type annotations for all exported variables and functions.

Changes

  • Added explicit type annotations for all constants: All exported constants now include explicit type annotations required by isolatedDeclarations:
    • RegExp constants: : RegExp
    • Numeric constraints (min, max, multipleOf, exclusiveMin, exclusiveMax): : number
    • Default values: Dynamic type inference based on value type (string, number, boolean, Date, Record<string, unknown>, unknown[], readonly unknown[])

Configuration Updates

  • Enabled isolatedDeclarations in TypeScript configs: Added isolatedDeclarations: true to:
    • packages/zod/tsconfig.json
    • packages/zod/tsconfig.build.json
    • tests/tsconfig.json
    • tests/configs/zod.config.ts (added tsconfig reference to all output configurations)

Test Updates

  • Updated all test assertions to expect the new format with explicit type annotations
  • Fixed stripNill function in tests/mutators/zod-preprocess.ts to include explicit return type annotation

Why This Change?

TypeScript's isolatedDeclarations feature ensures that .d.ts files can be generated independently without analyzing the implementation files. This improves build performance and enables better tooling support. However, it requires explicit type annotations for:

  • Exported variables (including constants)
  • Exported functions
  • Variables that are inferred from other sources

By adding these annotations, we ensure that generated Zod schemas work seamlessly with projects that have isolatedDeclarations enabled, which is becoming a common requirement in modern TypeScript projects.

Testing

  • All existing tests pass (97/97)
  • Generated Zod files compile successfully with isolatedDeclarations: true
  • Type declarations are generated correctly for all schema types

Backward Compatibility

This change is fully backward compatible. The generated code still works in projects without isolatedDeclarations enabled, and the functionality remains unchanged. The only difference is the addition of explicit type annotations, which is a TypeScript best practice regardless of the isolatedDeclarations setting.

Typescript: Support --isolatedDeclarations
Typescript: Support --isolatedDeclarations
update samples
Added support for "as const satisfies readonly"
@sentik
Copy link
Contributor Author

sentik commented Nov 4, 2025

Also added as const satisfies Pattern

Additional Enhancement: as const satisfies Pattern

In addition to the explicit type annotations required for isolatedDeclarations, we've also added the as const satisfies pattern to preserve literal types and improve type inference. This pattern combines the benefits of:

  • as const: Narrowing types to their literal values (e.g., "hello" instead of string)
  • satisfies: Type checking without widening the inferred type (crucial for isolatedDeclarations)

Why This Matters

1. String Enums - Better Type Safety

// Without as const satisfies:
zod.enum(['cat', 'dog'])  // Type: string[]

// With as const satisfies:
zod.enum(['cat', 'dog'] as const satisfies readonly string[])  // Type: readonly ['cat', 'dog']

Benefits:

  • Preserves exact literal types ('cat' | 'dog' instead of string)
  • Enables better autocomplete and type checking
  • Works seamlessly with isolatedDeclarations requirements

2. Arrays - Preserving Element Types

// Default values for arrays with enum items:
export const testEnumArrayDefault: readonly string[] = 
  ["A"] as const satisfies readonly string[];

Benefits:

  • Maintains tuple-like behavior for array defaults
  • Ensures type compatibility with Zod's enum array validation
  • Prevents accidental type widening

3. Objects - Literal Property Preservation

// Default values for objects:
export const petDefault: Record<string, unknown> = 
  { name: "Fluffy", age: 3 } as const satisfies Record<string, unknown>;

Benefits:

  • Preserves literal types for object properties (name: "Fluffy" vs name: string)
  • Maintains type safety while satisfying the Record<string, unknown> constraint
  • Enables better inference when the default is used in validation

4. Enum Arrays in Objects - Complex Nested Types

zod.array(zod.enum(['A', 'B', 'C'] as const satisfies readonly string[]))

Benefits:

  • Proper type inference for nested enum arrays
  • Maintains literal types throughout the validation chain
  • Compatible with isolatedDeclarations requirements

TypeScript isolatedDeclarations Compatibility

The satisfies operator is essential for isolatedDeclarations because:

  • It performs type checking without changing the inferred type
  • It allows explicit type annotations required by isolatedDeclarations while preserving literal types
  • It ensures generated .d.ts files contain accurate type information

Example Comparison

Before:

// Type inference loses literal information
const enumValues = ['cat', 'dog'];  // Type: string[]
zod.enum(enumValues);  // Zod receives: string[]

After:

// Literal types preserved, type-safe, isolatedDeclarations-compatible
const enumValues = ['cat', 'dog'] as const satisfies readonly string[];  
// Type: readonly ['cat', 'dog']
zod.enum(enumValues);  // Zod receives: readonly ['cat', 'dog']

This enhancement ensures that generated Zod schemas provide the best possible TypeScript experience while remaining fully compatible with isolatedDeclarations mode.

@melloware
Copy link
Collaborator

Looks like tests are failing?

@melloware melloware added the zod Zod related issue label Nov 4, 2025
@melloware melloware added this to the 8.0.0-rc.2 milestone Nov 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

zod Zod related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants