Records
Record schemas are used to validate types such as Record<string, number>
. This is particularly useful for storing or caching items by ID.
const User = z.object({ name: z.string() });
const UserStore = z.record(z.string(), User);
type UserStore = z.infer<typeof UserStore>;
// => Record<string, { name: string }>
The schema and inferred type can be used like so:
const userStore: UserStore = {};
userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
name: "Carlotta"
}; // passes
userStore["77d2586b-9e8e-4ecf-8b21-ea7e0530eadd"] = {
whatever: "Ice cream sundae"
}; // TypeError
A note on numerical keys
While z.record(keyType, valueType)
is able to accept numerical key types and TypeScript's built-in Record type is Record<KeyType, ValueType>
, it's hard to represent the TypeScript type Record<number, any>
in Zod.
As it turns out, TypeScript's behavior surrounding [k: number]
is a little unintuitive:
const testMap: { [k: number]: string } = {
1: "one"
};
for (const key in testMap) {
console.log(`${key}: ${typeof key}`);
}
// prints: `1: string`
As you can see, JavaScript automatically casts all object keys to strings under the hood. Since Zod is trying to bridge the gap between static and runtime types, it doesn't make sense to provide a way of creating a record schema with numerical keys, since there's no such thing as a numerical key in runtime JavaScript.