Skip to main content

Validation with Zod

Extended Zod schemas with FiveM handle type support for runtime validation.

Overview

True Life uses Zod for runtime schema validation. The @core/zod module extends Zod with schemas for FiveM's typed handle system.

Why Handle Schemas?

FiveM uses branded number types (HEntity, HPed, HVehicle, etc.) for compile-time type safety. These schemas validate and transform plain numbers into properly typed handles.

Usage

import { z } from "@core/zod";
 
// Standard Zod schemas work as expected
const playerSchema = z.object({
	name: z.string(),
	health: z.number(),
});
 
// FiveM handle schemas for entity handles
const spawnEventSchema = z.object({
	entity: z.hentity(),
	ped: z.hped(),
	vehicle: z.hvehicle(),
});
 
// Parse validates and transforms to typed handles
const data = spawnEventSchema.parse({
	entity: 12345,
	ped: 67890,
	vehicle: 11111,
});
// data.entity is typed as HEntity
// data.ped is typed as HPed
// data.vehicle is typed as HVehicle

Available Handle Schemas

SchemaHandle TypeDescription
z.handle()HandleGeneric handle
z.hentity()HEntityAny entity
z.hped()HPedPedestrians/NPCs
z.hvehicle()HVehicleVehicles
z.hobj()HObjWorld objects
z.hcam()HCamCameras
z.hblip()HBlipMap blips
z.hplayer()HPlayerPlayers
z.hpickup()HPickupPickups
z.hinterior()HInteriorInteriors
z.hfireId()HFireIdFire instances

Common Patterns

RPC Payload Validation

const transferSchema = z.object({
  fromAccount: z.string(),
  toAccount: z.string(),
  amount: z.number().positive(),
});
 
@Server
async transfer(ctx: EventContext<[payload: unknown]>): Promise<Result> {
  const [rawPayload] = ctx.args;
  const payload = transferSchema.parse(rawPayload);
  // payload is now typed and validated
}

Entity Event Validation

const damageEventSchema = z.object({
	victim: z.hped(),
	attacker: z.hped().optional(),
	damage: z.number(),
	weaponHash: z.number(),
});

Best Practices

  1. Validate at boundaries - Parse external data (NUI, events) early
  2. Use handle schemas - Maintain type safety across serialization
  3. Define schemas near usage - Keep schemas with their consuming code