Added AI skills
This commit is contained in:
88
.agents/skills/zod/references/schema-use-unknown-not-any.md
Normal file
88
.agents/skills/zod/references/schema-use-unknown-not-any.md
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
title: Use z.unknown() Instead of z.any()
|
||||
impact: CRITICAL
|
||||
impactDescription: z.any() bypasses TypeScript's type system entirely; z.unknown() forces type narrowing before use
|
||||
tags: schema, unknown, any, type-safety
|
||||
---
|
||||
|
||||
## Use z.unknown() Instead of z.any()
|
||||
|
||||
`z.any()` infers to `any` type, disabling TypeScript's type checking for that value. `z.unknown()` infers to `unknown`, which forces you to narrow the type before using it. This preserves type safety while still allowing any input.
|
||||
|
||||
**Incorrect (using z.any):**
|
||||
|
||||
```typescript
|
||||
import { z } from 'zod'
|
||||
|
||||
const eventSchema = z.object({
|
||||
type: z.string(),
|
||||
payload: z.any(), // Infers to 'any'
|
||||
})
|
||||
|
||||
type Event = z.infer<typeof eventSchema>
|
||||
// { type: string; payload: any }
|
||||
|
||||
function handleEvent(event: Event) {
|
||||
// No type error - TypeScript allows anything
|
||||
console.log(event.payload.foo.bar.baz) // Runtime crash if structure is wrong
|
||||
}
|
||||
```
|
||||
|
||||
**Correct (using z.unknown):**
|
||||
|
||||
```typescript
|
||||
import { z } from 'zod'
|
||||
|
||||
const eventSchema = z.object({
|
||||
type: z.string(),
|
||||
payload: z.unknown(), // Infers to 'unknown'
|
||||
})
|
||||
|
||||
type Event = z.infer<typeof eventSchema>
|
||||
// { type: string; payload: unknown }
|
||||
|
||||
function handleEvent(event: Event) {
|
||||
// TypeScript error: Object is of type 'unknown'
|
||||
console.log(event.payload.foo) // Won't compile
|
||||
|
||||
// Must narrow type first
|
||||
if (typeof event.payload === 'object' && event.payload !== null) {
|
||||
// Now TypeScript knows it's an object
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Better approach with discriminated unions:**
|
||||
|
||||
```typescript
|
||||
import { z } from 'zod'
|
||||
|
||||
const userCreatedSchema = z.object({
|
||||
type: z.literal('user.created'),
|
||||
payload: z.object({
|
||||
userId: z.string(),
|
||||
email: z.string().email(),
|
||||
}),
|
||||
})
|
||||
|
||||
const orderPlacedSchema = z.object({
|
||||
type: z.literal('order.placed'),
|
||||
payload: z.object({
|
||||
orderId: z.string(),
|
||||
amount: z.number(),
|
||||
}),
|
||||
})
|
||||
|
||||
const eventSchema = z.discriminatedUnion('type', [
|
||||
userCreatedSchema,
|
||||
orderPlacedSchema,
|
||||
])
|
||||
|
||||
// Full type safety for each event type
|
||||
```
|
||||
|
||||
**When NOT to use this pattern:**
|
||||
- When you're consuming a third-party API where you truly don't know the shape
|
||||
- When prototyping and will add proper types later
|
||||
|
||||
Reference: [Zod API - unknown](https://zod.dev/api#unknown)
|
||||
Reference in New Issue
Block a user