4

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
}
Nicolas Bouvrette
  • 4,295
  • 1
  • 39
  • 53
  • You can use JSON Schema and [Ajv JSON Schema validator](https://ajv.js.org/). You will however need to define JSON Schemas e.g. for your API but that's great documentation and anyone using your API would exactly know what to send to your API. – Mushroomator Sep 28 '22 at 19:46
  • This is exactly what I am trying to avoid. I don't want to write type guard but rather infer the type's properties at runtime. – Nicolas Bouvrette Sep 28 '22 at 19:46
  • I saw Ajv but it doesn't look like you can actually use the schemas as type - I was looking for something native to TypeScript ideally – Nicolas Bouvrette Sep 28 '22 at 19:49
  • The type system is _gone_ at runtime. So if you can't know the possible types at compile time, _then you can't know the possible types_. – Alex Wayne Sep 28 '22 at 19:50
  • @NicolasBouvrette - There is no such thing native to TypeScript – Tobias S. Sep 28 '22 at 19:50
  • I found this post which is a bit old but it looks like this is still not possible today? https://stackoverflow.com/questions/16013667/detect-whether-object-implement-interface-in-typescript-dynamically – Nicolas Bouvrette Sep 28 '22 at 19:54
  • Might want to check out [ts-auto-guard](https://github.com/rhys-vdw/ts-auto-guard), or [my abandoned project](https://kelsny.github.io/synth/#generate-type-guards) for some ideas. – kelsny Sep 28 '22 at 20:37
  • I actually just edited what I find a decent answer... too bad I cannot add it as an answer since the question is closed :) – Nicolas Bouvrette Sep 28 '22 at 20:46

0 Answers0