Validating returns against types
This is more of a question then a feature request (at least at this point), but am I reading the generated code correctly as not actually validating that the response returned by the http request matches the type/schema promised by the OpenAPI spec? I.e., if the schema for the response of GET /foo?id=1 is, say:
{
id: number
name: string
address: string
}
the generated typescript logic will (on success) assert that the returned type has that form, but it won't actually check that it does? Or am I missing something?
If I'm correct, have you given any thought to using a generated typeguard to ensure that the data returned actually has the type expected based on the API spec? i.e., something like (in the example above):
function isValid<Response>(obj:any):obj is Response
where Response is the generated type and a return of false from this function would lead to an APIError? Presumably you'd have to generate a typeguard for each generated type and then use it in the request.ts
Thanks!
This is my biggest gripe with all the different TypeScript OpenAPI clients out there. They aren't actually type safe! They all in the end do what is essentially an unsafe cast from any to one of the generated types. They need a type guard or to use zod, io-ts, or some other library that can generate type guards (although relying on those when we're doing code generation anyway is probably not needed).
I started hacking on something here: https://github.com/ferdikoomen/openapi-typescript-codegen/pull/1195. Far from complete. Want to check if this is wanted feature first.
A few additional thoughts on this:
- ts-auto-guard is a nice project for generating type-guards from types. Actually, our current solution is we use openapi-typescript-codegen to generate the types and ts-auto-guard to generate the guards and then just roll our own api that uses the guard. (Generate the types and guards is the tedious part)
- In truth, I think what would be ideal is not just auto-generated type-guards but actually autogenerated validators that are capable of generating validation logic based on the full scope of openapi annotations. You could, of course, make those validators into type guards as well using the type predicate return, but because this is generated code I think the validation logic is actually more important than the resulting type safety. In other words, in generated code, validator+type assertion is probably fine since you aren't manually mucking around with the code in between the validation and the assertion of the type.
Re (2) I agree (and planned to do so). It can just be folded into the "type" guard.
Unfortunately since I wrote this I've run into #942. Without control of the axios instance this library is a no go for us in production so I don't think I will continue working on the above PR. #942 seems hard to fix as the request.ts extension mechanism requires relying on global state for your axios instance as there's no way to communicate information from the client class to the request.ts module.