I'm working on an API (this is my first time in TypeScript). Traditionally you would type the response you would expect in the response.body
of your API, something like this:
type ApiProps = {
name: string
email: string
}
Now if I want to know that response.body
is an ApiProps
object, from all the posts. I have found you have to write a type guard manually, doing all the checks. Isn't there a way to avoid writing manually all those type checks? something like:
function hasValidProps<T>(body: unknown): body is T {
// some code using the type definition to validate the type "automatically"
}
Edit: Apparently in 2022 this is still not doable, but I did find a decent workaround below
function hasValidProps<T extends Record<string, unknown> = Record<string, unknown>>(
body: unknown,
props: T
): body is T {
try {
const bodyObject = JSON.parse(body as string) as Record<string, unknown>
const bodyObjectKeys = Object.keys(bodyObject)
const isValid = Object.keys(props).every((key) => bodyObjectKeys.includes(key))
if (isValid) {
body = bodyObject
}
return isValid
} catch {
return false
}
}
const apiProps = {
name: '',
email: ''
}
export type ApiProps = typeof apiProps
// And in your API check...
if (!hasValidProps<ApiProps>(request.body, apiProps)) {
response.status(400).end()
return
}