Skip to content

TypeScript type checking inconsistency with ConfigService Zod validation #2182

@Miguiz

Description

@Miguiz

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

I found a type checking inconsistency in @nestjs/config when using ConfigService with Zod schema containing optional fields.

The ValidatedResult type is defined as:

type ValidatedResult<WasValidated extends boolean, T> = 
    WasValidated extends true ? T : T | undefined;

When using ConfigService with a Zod schema containing optional fields, TypeScript behaves inconsistently:

// Zod schema
const schema = z.object({
    API_KEY: z.string().optional()  // Type: string | undefined
});
type Config = z.infer<typeof schema>;

// Service
class Service {
    private apiKey: string;  // Note: strict type string
    
    constructor(private config: ConfigService<Config, true>) {
        // Should error: assigning string | undefined to string
        this.apiKey = this.config.get('API_KEY', { infer: true });  // No TypeScript error!
    }
}

Current behavior:

  • With ConfigService<Config, true>: TypeScript doesn't emit an error when assigning string | undefined to string
  • With ConfigService<Config, false>: TypeScript correctly emits a type error
  • Both should emit an error since the return type is string | undefined in both cases (due to Zod's .optional())

Minimum reproduction code

All in steps to reproduce

Steps to reproduce

// schema.ts
import { z } from 'zod';

const schema = z.object({
    KEY: z.string().optional()
});

type Config = z.infer<typeof schema>;

// service.ts
import { ConfigService } from '@nestjs/config';

class Service {
    private key: string;
    
    constructor(private config: ConfigService<Config, true>) {
        // Should error but doesn't
        this.key = this.config.get('KEY', { infer: true });
    }
}

Expected behavior

TypeScript should emit a type error in both cases (true and false) since we're trying to assign a string | undefined to a string type.

NestJS version

^11.0.1

Packages versions

        "@nestjs/common": "^11.0.1",
        "@nestjs/config": "^4.0.0",
        "@nestjs/core": "^11.0.1",
        "zod": "^4.0.0",
        "typescript": "^5.7.3",

Node.js version

22

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

The bug seems related to how NestJS handles type inference with the WasValidated parameter in the ValidatedResult type. The true parameter appears to bypass type checking in an unexpected way.

Let me know if you need any additional information to investigate this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions