-
Notifications
You must be signed in to change notification settings - Fork 91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using optional environment variables leads to 'undefined' string value and incorrectly inferred type #1302
Comments
IMO, it would make more sense if the return type of an unvalidated Example class Env {
@IsInt()
PORT!: number;
}
const configService: ConfigService<Env> = app.get(ConfigService);
const port = configService.get('PORT', {infer: true}) The type of In general, the |
but that's because you're using env. vars, right? I could have a config with hard coded values as well. Then, the source of true must be that That's why the default is works like that and probably won't change. Is a way to avoid boilerplate code for common use cases. There are others libs for such task in nestjs ecosystem that could satisfy your needs, see https://github.com/nestjs/awesome-nestjs |
@micalevisk, I don't really understand what you're trying to say.
The fact is, the return type is incorrect and what I'm guessing you're saying is that this is on purpose because there would be more burden on users of Nest that do not care about type safety? If this is the case, it seems troubling to me. That being said, the main problems addressed in this issue still stand regardless. Going back to your example, say that your hardcoded config has an optional property, the validated return type would be wrong. Example: class Env {
OPT?: string
}
const configService = app.get<ConfigService<Env, true>>(ConfigService);
const opt = configService.get('OPT', {infer: true}) // Is: string, Should be string | undefined I will have a look at https://github.com/Nikaple/nest-typed-config from the awesome-nestjs repository you linked. |
in your last example, we indeed got a wrong type. I don't recall exactly why we remove the interface Env {
optionalString?: string
mandatoryString: string
}
const configService = app.get<ConfigService<Env, true>>(ConfigService);
const opt = configService.get('optionalString', {infer: true}) // must be string | undefined
const mand = configService.get('mandatoryString', {infer: true}) // must be string |
The removal Lines 16 to 19 in f1abd2d
to type ExcludeUndefinedIf<
ExcludeUndefined extends boolean,
T,
> = ExcludeUndefined extends true ? T : T | undefined; This works for the example you provided and for mine. Regarding breaking changes, this would result in type errors for users with class Env {
mandatoryString?: string
}
const configService = app.get<ConfigService<Env, true>>(ConfigService);
const hasCat = configService.get('mandatoryString', {infer: true}).includes('🐱') However, I would argue that their types are wrong and this was hidden by the |
I'm fine with such breaking change for the next major release. Let's see what Kamil thinks on this. You could open a PR already if you want to. Thanks! |
@micalevisk, I'm definitely willing to create a PR incorporating this change. One thing to note though is that while this change fixes the 2nd point of the issue, it does not fix point 1:
Do you want me to hold off from creating a PR until that point is addressed/discussed/triaged or would you like a separate PR that only addresses the types (point 2)? I already have an idea about how to fix point 1 but I'm not sure why the config is assigned back to |
I'm not entirely sure on why is this either. So you can create a PR for point 2 only, for now |
As for 2 let's track this here #1304 |
I believe this is closed prematurely as one of the issues is not addressed.
You say that [env files] should never contain any complex values. What would be wrong with an env file like this: SOME_JWT=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c where upon parsing, the Even if you were to put this aside, having an optional environment variable leads to I would be willing to make a PR to help clear this up and fix this issue. |
For this, you should rather use a configuration factory/namespace, but I see where you're coming from so I would be more than happy to see a PR addressing this use-case |
Is there an existing issue for this?
Current behavior
One of my environment variables,
OPT
, is optional. I use theConfigModule.validate
function which returns an object with theOPT
key havingundefined
as value. The following problems occur:Using
ConfigService.get('OPT')
returns the string value'undefined'
This is because
ConfigModule.forRoot
assigns all validated config key-value pairs toprocess.env
which leads to stringification and consequentConfigService.get
returning the stringified value fromprocess.env
The stringification is caused here:
config/lib/config.module.ts
Lines 194 to 203 in d368ed1
Return type from
ConfigService<EnvironmentVariables, true>.get
excludes undefinedThe second generic parameter (
WasValidated
) changes the return value ofConfigService.get
. Iftrue
, it removesundefined
from the return type. Iffalse
, it addsundefined
. The problem here is that a value could be both validated andundefined
. Observe the TypeScript return type ofoptValue
inmain.ts
.Minimum reproduction code
https://github.com/MatthiasKunnen/nest-config-service-optional-env-var
Steps to reproduce
No response
Expected behavior
1
assignVariablesToProcess
should not assign'undefined'
or any object value toprocess.env
. The current behavior could even result in runtime errors in the future as stringification of non-string/number/boolean is deprecated. See docs:I'm actually quite intrigued as to why the validated config is assigned to
process.env
? It could contain complex values such as instances of classes which could not lend themselves to being stringified.2
The return type of
ConfigService.get
should includeundefined
for optional properties of validated configs.Package version
2.3.1
NestJS version
9.0.11
Node.js version
18.16.0
In which operating systems have you tested?
Other
Optional environment variables are not a strange concept. They should work without hiccups and could benefit from documentation at https://docs.nestjs.com/techniques/configuration.
The text was updated successfully, but these errors were encountered: