-
-
Save benceg/5f4b6398b9e3ba164d494793808af407 to your computer and use it in GitHub Desktop.
Tip: Use Zod for Safety
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import settings from "./settings.json"; | |
export interface DataSchema { | |
title: string; | |
author?: string; | |
content: string; | |
} | |
type ExpectedResponse = | |
| { success: true; data: DataSchema } | |
| { success: false; error: Error }; | |
export const getData = async (): Promise<ExpectedResponse> => { | |
try { | |
// settings.endpoint may not be a valid URL. | |
const response = await fetch(settings.endpoint); | |
const data = await response.json(); | |
// TypeScript will assume this to be correct, even though | |
// we could have received any data in lieu of what we expect. | |
// We might therefore return unusable data. | |
return { success: true, data: data as DataSchema }; | |
} catch (error) { | |
return { success: false, error: error as Error }; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as z from 'zod'; | |
import settings from './settings.json'; | |
// Declare these schemas as Zod objects rather than interfaces. | |
const settingsSchema = z.object({ | |
endpoint: z.string().url(), | |
}); | |
const dataSchema = z.object({ | |
title: z.string(), | |
author: z.string().optional(), | |
content: z.string(), | |
}); | |
export type DataSchema = z.infer<typeof dataSchema>; | |
type ExpectedResponse = | |
| { success: true; data: DataSchema } | |
| { success: false; error: Error; } | |
// If validation fails in the global scope, our application will | |
// fail to run and will throw an error detailing any schema mismatches. | |
settingsSchema.parse(settings); | |
export const getData = async (): Promise<ExpectedResponse> => { | |
try { | |
// We can now rest assured that settings.endpoint is a URL. | |
const response = await fetch(settings.endpoint); | |
const data = await response.json(); | |
// We have a guarantee that any data sent alongside { success: true } | |
// is usable where it is required. | |
return dataSchema.safeParse(data); | |
} catch (error) { | |
return { success: false, error: error as Error }; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment