Typesikker miljøkonfiguration og runtime-validering
Validér miljøvariabler og eksternt input ved runtime med skemabiblioteker, der udleder statiske typer.
Typesikker miljøkonfiguration og runtime-validering er en gratis Bootcamp i backendudvikling med Node.js-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Bootcamp i backendudvikling med Node.js, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Bootcamp i backendudvikling med Node.js-kurset indeholder 4 lektioner i alt.
Hvorfor validere process.env?
I Node.js er alle værdier i process.env en streng eller undefined — køretiden giver dig ingen garantier.
process.env.PORTkan være"3000",""eller mangle helt.- En slåfejl som
DATABSE_URLgiver ubemærket værdienundefined. - TypeScript typer
process.envsomRecord<string, string | undefined>, så den kan ikke finde manglende nøgler.
Hvis du læser konfigurationen tilfældigt rundt omkring i din app, opstår nedbrud dybt inde i forespørgselshåndteringer — længe efter opstart. Løsningen er at validere én gang ved opstart og stoppe hurtigt med en tydelig meddelelse.
// Untyped, unsafe access scattered everywhere
const port = process.env.PORT; // string | undefined
const dbUrl = process.env.DATABASE_URL; // string | undefined
console.log(typeof port); // "string" or "undefined"
console.log(Number(process.env.MISSING)); // NaN — silent failureSkemabiblioteker og typeudledning
Et skemabibliotek giver dig mulighed for at beskrive datas form og begrænsninger én gang, derefter validere ved kørsel OG udlede en statisk TypeScript-type fra den samme definition.
- Populære valg: Zod, Valibot, ArkType, TypeBox.
- Én sandhedskilde — skemaet — leverer både kontrollen ved kørsel og typen ved kompilering.
- Ingen duplikeret
interface, der kan komme ud af trit.
Vi bruger Zod, som er det mest almindelige valg i Node.js-økosystemet. z.infer<typeof schema> udleder den type, som skemaet validerer.
import { z } from "zod";
const UserSchema = z.object({
id: z.number().int(),
email: z.string().email(),
});
// Static type inferred from the runtime schema
type User = z.infer<typeof UserSchema>;
// type User = { id: number; email: string }Et første miljøskema
Lad os beskrive det miljø, som vores tjeneste har brug for. Da værdierne i process.env altid er strenge, skal skemaet konvertere numeriske felter og begrænse strengfelter.
z.coerce.number()omdanner"3000"til3000.z.enum([...])begrænser en værdi til et fast sæt.- Kædning som
.min()/.url()tilføjer begrænsninger ved kørsel.
Definér skemaet i sit eget modul (for eksempel src/env.ts), så det importeres én gang ved opstart.
import { z } from "zod";
export const EnvSchema = z.object({
NODE_ENV: z.enum(["development", "test", "production"]),
PORT: z.coerce.number().int().positive().default(3000),
DATABASE_URL: z.string().url(),
JWT_SECRET: z.string().min(32),
});Parsing ved opstart
Kald schema.parse(process.env) én gang øverst i din startfil. Hvis valideringen mislykkes, kaster Zod en ZodError, og processen afsluttes, før den modtager trafik.
parse()returnerer et fuldt typet og valideret objekt.- Konverterede og standardiserede værdier er allerede anvendt.
- Eksportér resultatet, så resten af appen importerer et typet
env-objekt i stedet for at tilgåprocess.envdirekte.
import { z } from "zod";
import { EnvSchema } from "./env-schema";
export const env = EnvSchema.parse(process.env);
// env.PORT is number, env.NODE_ENV is a narrowed union
const server = createServer();
server.listen(env.PORT, () => {
console.log(`Listening on ${env.PORT} in ${env.NODE_ENV}`);
});safeParse til venlige fejlmeddelelser
En rå staksporingsrapport fra ZodError er støjende. Brug safeParse til at få et resultatobjekt, som du kan formatere til en letlæselig opstartsmeddelelse, og afslut derefter bevidst.
safeParsereturnerer{ success: true, data }eller{ success: false, error }— den kaster aldrig en fejl.error.flatten().fieldErrorsgrupperer meddelelser pr. felt.- Afslut med
process.exit(1), så orkestratorer (Docker, PM2, k8s) registrerer en mislykket opstart.
import { z } from "zod";
const EnvSchema = z.object({
PORT: z.coerce.number().int().positive(),
DATABASE_URL: z.string().url(),
});
const parsed = EnvSchema.safeParse(process.env);
if (!parsed.success) {
console.error("Invalid environment variables:");
console.error(parsed.error.flatten().fieldErrors);
process.exit(1);
}
export const env = parsed.data;Et selvstændigt, kørbart eksempel
Her er en selvstændig demonstration af mønsteret med validering efterfulgt af typeudledning. Den bruger et almindeligt objekt i stedet for process.env, så en online-dommer kan køre den uden opsætning.
Den viser konvertering, en standardværdi, en enum og en venlig fejlsti — de samme teknikker, som du ville bruge til indlæsning af et rigtigt miljø.
import { z } from "zod";
const Schema = z.object({
NODE_ENV: z.enum(["development", "production"]).default("development"),
PORT: z.coerce.number().int().positive(),
});
function loadConfig(raw) {
const result = Schema.safeParse(raw);
if (!result.success) {
throw new Error(JSON.stringify(result.error.flatten().fieldErrors));
}
return result.data;
}
const config = loadConfig({ PORT: "8080" });
console.log(config); // { NODE_ENV: 'development', PORT: 8080 }
console.log(typeof config.PORT); // numberIndlæsning af .env-filer med ESM
Lokalt gemmer du konfiguration i en .env-fil. Biblioteket dotenv læser den ind i process.env. Med ESM og TypeScript skal du indlæse den før ethvert modul, der læser konfiguration.
- Moderne Node (v20.6+) har et indbygget flag,
--env-file=.env— ingen afhængighed er nødvendig. - Hvis du bruger
dotenv, skal du kaldedotenv/confighelt øverst, fordi ESM-importer løftes og evalueres først. - Commit aldrig rigtige hemmeligheder; commit en
.env.example, der dokumenterer de nødvendige nøgler.
// Option A: built-in (Node 20.6+), no import needed
// $ node --env-file=.env dist/index.js
// Option B: dotenv — must run first
import "dotenv/config";
import { EnvSchema } from "./env-schema";
export const env = EnvSchema.parse(process.env);Genbrug af skemaet til input fra forespørgsler
Præcis den samme tilgang validerer usikkert input fra kørselstiden — forespørgselsbrødtekster, forespørgselsparametre og webhook-nyttedata. Netværksdata er lige så utypede som process.env.
- Definér et skema pr. slutpunkt, og kør derefter
parsepå den indkommende JSON. - Ved fejl skal du svare med
400i stedet for at få processen til at gå ned. - Det parsede resultat er fuldt typet for resten af håndteringen.
import { z } from "zod";
const CreateUserBody = z.object({
email: z.string().email(),
age: z.coerce.number().int().min(0).optional(),
});
function handleCreateUser(rawBody, res) {
const result = CreateUserBody.safeParse(rawBody);
if (!result.success) {
res.status(400).json({ errors: result.error.flatten() });
return;
}
const body = result.data; // { email: string; age?: number }
// ...persist body
}Transformationer og afledt konfiguration
Skemaer kan transformere værdier under parsing og dermed producere konfiguration, der er klar til brug. Det holder konverteringslogikken tæt på valideringsreglen.
.transform()omdanner en valideret værdi til en ny form.- Miljøstrenge med kommaseparerede værdier bliver til arrays; flag bliver til boolske værdier.
- Den udledte type afspejler det transformerede output, ikke det rå input.
import { z } from "zod";
const EnvSchema = z.object({
// "a.com,b.com" -> ["a.com", "b.com"]
CORS_ORIGINS: z.string()
.transform((s) => s.split(",").map((o) => o.trim()))
.pipe(z.array(z.string().url())),
// "true"/"false" string -> boolean
ENABLE_CACHE: z
.enum(["true", "false"])
.transform((v) => v === "true")
.default("false"),
});Regler på tværs af felter med refine
Nogle gange afhænger gyldigheden af forholdet mellem felter — for eksempel skal en hemmelighed være angivet i produktion, mens en standardværdi er fin lokalt. Brug .refine() eller .superRefine() på objektskemaet.
- Kontrollen køres, efter at de enkelte felter er parset.
- Du knytter en brugerdefineret meddelelse og en
pathtil, så fejlen peger på det rigtige felt. - På den måde udtrykker du forretningsregler, som et fladt skema med regler pr. felt ikke kan udtrykke.
import { z } from "zod";
const EnvSchema = z
.object({
NODE_ENV: z.enum(["development", "production"]),
SENTRY_DSN: z.string().url().optional(),
})
.refine(
(e) => e.NODE_ENV !== "production" || !!e.SENTRY_DSN,
{ message: "SENTRY_DSN is required in production", path: ["SENTRY_DSN"] }
);Eksport af en typet konfigurationssingleton
Målet er, at resten af din kodebase aldrig tilgår process.env. Den importerer ét valideret og typet env-objekt.
- Centraliseret adgang betyder, at TypeScript kan foreslå alle nøgler og markere slåfejl ved kompilering.
- Hvis du omdøber en variabel, kræver det kun en ændring i én fil.
- Test kan importere et skema og give det mockobjekter i stedet for at ændre global tilstand.
// src/config.ts
import "dotenv/config";
import { z } from "zod";
const EnvSchema = z.object({
NODE_ENV: z.enum(["development", "test", "production"]).default("development"),
PORT: z.coerce.number().int().positive().default(3000),
DATABASE_URL: z.string().url(),
});
const parsed = EnvSchema.safeParse(process.env);
if (!parsed.success) {
console.error("❌ Invalid env:", parsed.error.flatten().fieldErrors);
process.exit(1);
}
export const env = Object.freeze(parsed.data);
// elsewhere: import { env } from "./config";Hurtigt tjek
Test din forståelse af mønsteret for typesikker konfiguration.
Opsummering
Du har lært at gøre konfiguration og eksternt input typesikkert i moderne Node.js:
- Hvorfor:
process.envog netværksdata er utypede strenge; validér én gang og stop hurtigt ved fejl. - Skemaer: et bibliotek som Zod giver validering ved kørsel samt udledte statiske typer fra én definition (
z.infer). - Indlæsning af miljø: konvertér tal, begræns med enum-værdier og standardværdier, og indlæs
.envvia--env-fileellerdotenv/configfør læsning. - safeParse: formatér
error.flatten().fieldErrors, og kaldprocess.exit(1)ved fejl. - Ud over miljøet: genbrug skemaer til forespørgselsbrødtekster, tilføj
.transform()til afledt konfiguration og.refine()til regler på tværs af felter. - Resultat: eksportér én frosset, typet
env-singleton, som hele appen importerer.
Lær JavaScript med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 22
- Lektioner
- 92
Ofte stillede spørgsmål
Er lektionen “Typesikker miljøkonfiguration og runtime-validering” gratis?
Ja — hele teksten til “Typesikker miljøkonfiguration og runtime-validering” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Bootcamp i backendudvikling med Node.js-kurset, skal du opgradere til CoddyKit PRO. Bootcamp i backendudvikling med Node.js-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Typesikker miljøkonfiguration og runtime-validering”?
Validér miljøvariabler og eksternt input ved runtime med skemabiblioteker, der udleder statiske typer. Du øver dig i Bootcamp i backendudvikling med Node.js med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Bootcamp i backendudvikling med Node.js?
Der kræves ingen tidligere erfaring. Bootcamp i backendudvikling med Node.js på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.
Hvor lang tid tager lektionen “Typesikker miljøkonfiguration og runtime-validering”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Bootcamp i backendudvikling med Node.js-lektion?
Ja. Alle Bootcamp i backendudvikling med Node.js-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Migrering fra CommonJS til native ES-moduler
- Konfiguration af tsconfig til Node-backendprojekter
- Typesikker miljøkonfiguration og runtime-validering
- Hurtig iteration med tsx, hot reload og source maps