TypeScript type checking inconsistency with ConfigService Zod validation
Is there an existing issue for this?
- [x] 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 assigningstring | undefinedtostring - With
ConfigService<Config, false>: TypeScript correctly emits a type error - Both should emit an error since the return type is
string | undefinedin 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?
- [x] macOS
- [ ] Windows
- [x] 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.
Would you like to create a PR for this issue?
Me? I can try to fix it but I don't really know how to solve it.
@kamilmysliwiec @Miguiz I've submitted a fix in #2213