[Feature Request] Discriminating unions for generated types
Maintainers usually reply within 1 day
@theoephraim is already working on this.
Since Jul 1, 2026.
Assessment
This issue has not been assessed yet.
Description
Description
When a variable's "optionality" (probably not a word - sorry) depends on some other variable, like currentEnv, it would be really convenient if the generated types would reflect this.
In its simplest form, it would be something like this:
# @generateTypes(lang=ts, path=varlock.d.ts)
# @currentEnv=$APP_ENV
# ----------
# @type=enum(dev, staging, prod, building)
# @sensitive={preventLeaks=false}
APP_ENV=dev
# @optional=forEnv(building)
# @sensitive
DATABASE_PASSWORD=
Allowing the user to then make the following checks / assertions:
import { ENV } from 'varlock/env';
if (ENV.APP_ENV !== 'building') {
// in this scope, `ENV.DATABASE_PASSWORD` is of type `string`, and not `string | undefined`.
}
Motivation
The advantage of using varlock for us is not only that we can fetch secrets from one of the plugins before an application is initialized. It is also the fact that variables can depend on other variables, and generally the ability to script the the environment using the various resolver functions.
As we do not want to bake secrets into our docker containers, we have marked nearly every variable as @sensitive (with those that are actually public as @sensitive={preventLeaks=false} - a hack while waiting for #750 - although we cannot import this client-side, but that's outside the scope of this request).
A lot of our server side code needs to be initialized once the container is up and running, thus we a few checks like the one above in our codebase.
Since typescript solves this with discriminated unions, I would be very happy to see the implemented in varlock as well.
Proposed Solution
Generate the type declaration file along the following lines:
type CoercedEnvSchema
= | {
APP_ENV: 'dev' | 'staging' | 'prod';
DATABASE_PASSWORD: string;
} | {
APP_ENV: 'building';
DATABASE_PASSWORD?: string;
};
This is of course simplified - it would probably make sense to destructure the type definition into multiple types, as the complexity increases.
Alternatives
Using the "Non-null assertion" operator (!) on all the affected variables.
Creating a .env.building file, filled with mock variables has not really been a consideration - because that could lead misuse of the DATABASE_PASSWORD variable - trying to instantiate a database connection, when the variable is actually nonsense, making the application throw on build or similar.
With the non-null assertion check the developer manually checks that the environment is set properly.
Additional Information
I get that the complexity of this task quickly becomes huge, as the resolver functions can return more or less anything, so I would suggest limiting the functionality to begin with.
Like only supporting forEnv() in the @optional / @required decorators (and maybe other variables having @type=boolean @required decorators), when generating these type unions.
I would also be willing to assist in coming up with a proper algorithm for generating these types correctly.
- Dominant language
- TypeScript
- Stars
- 4.9k
- Forks
- 140
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 35
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from dmno-dev/varlock
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
dmno-dev/varlock#1279 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 69/100
dmno-dev/varlock#1100 · 3 comments ·
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 78/100
dmno-dev/varlock#1278 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 72/100
dmno-dev/varlock#1275 · 1 comment ·
Maintainers usually reply within 1 day
-
core:varlock RFC
Difficulty 5/5 Over a week Newbie friendliness 28/100
dmno-dev/varlock#1258 · 1 comment ·
Maintainers usually reply within 1 day
All issues in dmno-dev/varlock
Similar issues
-
documentation good first issue roadmap
Difficulty 1/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
resend/react-email#3876 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
siyuan-note/siyuan#21324 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
himynameisdave/bsky-profanity-counter#59 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100