Problem
Datenmodelle in TypeScript (TS) definieren ist super simpel – ein Interface oder Type ist schnell erstellt. Gut und schön. Aber wie wir wissen, nutzt das nur zur Kompilier-Zeit etwas. Was aber, wenn ich Laufzeit-kompatible Definitionen meiner Daten haben möchte? Das kann relevant werden, um Formulareingaben von Nutzer*innen zu validieren oder Payloads zu parsen, welche ich aus einem anderen System bekommen habe. In der Vergangenheit konnte man sich behelfen, indem man redundante Definitionen pflegen musste (ajv, joi), zwingend mit Klassen arbeiten musste (class-validator) oder aus "nicht-TS"-Schema-Definitionen TS-Dateien generiert werden mussten (openapi).
Lösung
Seit einiger Zeit gibt es eine Lib mit Namen zod. Diese erlaubt es, TS-Typen aus den definierten Schemas zu "inferieren". Das reduziert die Redundanz bei der Schema-Definition auf ein Minimum und erlaubt es, die Schemas zur Validierung bzw. zum Parsen zu benutzen.
Beispiel
const UserRoleSchema = z.enum( [ 'admin' , 'employee' , 'owner' ]) ;
type UserRole = z.infer<typeof UserRoleSchema>;
const UserSchema = z.object( {
id: z.string( ) ,
email: z.string( ) .email( ) ,
fullName: z.string( ) ,
role: UserRoleSchema ,
} ) :
type User = z.infer<typeof UserSchema> ;
const AddUserRequestSchema = UserSchema.omit( { id: true } ) ;
type AddUserRequest = z.infer<typeof AddUserRequestSchema>;
try {
const response = await httpClient.get<User>( 'users/me' ) ;
return await UserSchema.parseAsync (response.data) ;
} catch (e) {
console.error (e) ;
}
const parsedState = AddUserRequestSchema.safeParse ( state ) ;
if ( parsedState.success ) {
doSomething ( parsedState.data ) ;
}
Weitere Aspekte
- Das Ökosystem ist groß! Es gibt einige ähnliche Libs, die der Autor von zod auch dokumentiert: https://github.com/colinhacks/zod#comparison
- zod versucht sich an best practices zu orientieren, daher gibt es eine Unterscheidung zwischen z.enum und z.nativeEnum, wobei Ersteres eindeutig empfohlen wird.
---
Autor: Robert Gruner / Software Engineer / Standort Leipzig
Lust, das nächste ToiletPaper zu schreiben? Jetzt bei jambit bewerben!