-
-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Some strict TS narrowing is limiting parameter reuse #145
Comments
did you use the |
Ohhh, I didn't know it was required to reuse params. Looking at this method description, I was actually wondering its purpose: https://www.zodios.org/docs/api/helpers#asparameters Maybe it should have a minor change to emphasize it's required for params composition in asApi/apiBuilder |
But also Iooking at NarrowRaw definition, I don't see at first glance why parameter type couldn't be a standard union(Query | Header | Body) so it doesn't need the asParameter wrapper |
Yes unfortunately, yes you need to wrap into asParameters to infer the type correctly. Else typescript will complain the string are not literals. I'll improve the documentation to make this clearer. |
Fixed in version 9.1 :
|
I'm confused. Aren't Zod and Zodios both TypeScript-first libraries? I'm not a TypeScript expert, and I'm trying to read through the source code to figure out how to get even simple, simple scenarios to work properly in Zodios. The way TypeScript narrowing works here is making it really difficult to wrap, extend, or abstract Zodios into additional layers. E.g.: // Works:
const workingApi = makeApi([{
method: 'get',
path: '/api/users',
alias: 'getUsers',
response: z.string(),
parameters: [],
}]);
const endpoints = [{
method: 'get',
path: '/api/users',
alias: 'getUsers',
response: z.string(),
parameters: [],
}];
// Broken:
const brokenApi = makeApi(endpoints);
/*
Error: Argument of type '{ method: string; path: string; alias: string; response:
ZodString; parameters: never[]; }[]' is not assignable to parameter of type
'{ method: NarrowRaw<Method>; path: string; alias?: NarrowRaw<string | undefined>;
description?: string | undefined; requestFormat?: NarrowRaw<RequestFormat | undefined>;
... 5 more ...; errors?: NarrowRaw<...>; }[]'.
*/ I hate to be the old man shouting at clouds here, but if a developer is using a programming language, IDE, framework, or package that make it harder to perform the very simplest type of abstraction that a developer could possibly perform, I fail to see how that ecosystem could be appropriate for the developer. Maybe this just comes down to me not being a TypeScript expert, but I feel I shouldn't have to be an expert to pass a single variable into a single function. Here's another example: const workingApi = makeApi([{
method: 'get',
path: '/api/users',
alias: 'getUsers',
response: z.string(),
parameters: [],
}]);
const workingClient = new Zodios('/', workingApi);
// Works:
workingClient.getUsers();
const endpoints = [{
method: 'get',
path: '/api/users',
alias: 'getUsers',
response: z.string(),
parameters: [],
}];
const brokenApi = makeApi(endpoints as Parameters<typeof makeApi>[0]);
const brokenClient = new Zodios('/', brokenApi);
// Broken:
brokenClient.getUsers();
/*
Property 'getUsers' does not exist on type 'ZodiosInstance<{ method: NarrowRaw<Method>;
path: string; alias?: NarrowRaw<string | undefined>; description?: string | undefined;
requestFormat?: NarrowRaw<RequestFormat | undefined>; ... 5 more ...;
errors?: NarrowRaw<...>; }[]>'.ts(2339)
*/ I'm now searching through the Zodios source code to discover how I could possibly get around these issues. TypeScript is making me cynical. Now, whenever I see a claim like "Foo, a simple library for TypeScript users", I automatically translate that to "Foo, a simple library for TypeScript users with Ph.Ds in type casting, up casting, type guarding, type inference, type helpers, type narrowing, type widening, typing context, type literals, type symbols, inline typing, generic types, static type inference, dynamic type inference, compile-time type validation, run-time type validation, schema validation, covariance, contravariance, AST traversal, etc. etc. etc. Anyways, I've just come across other documented issues that recommend using the builders and internal client types, etc., so I'm going to give all of those things a shot on top of the hundred other things I've already tried. Thanks, TypeScript, you've made my life easier now that I don't have untyped variables. |
You need to use the helper makeApi or apiBuilder with parameters inlined. Else typescript can't infer literals and convert them to just a type of string and tuples into arrays. |
I kind of wonder whether having static type checking of API endpoints is really worth all the complication it introduces into the framework in terms of restrictions and workarounds. |
if it wasn't, tRPC and Zodios would not exist. |
If we define the parameters array outside of the parameter definition like this:
The typechecker complains with:
![image](https://user-images.githubusercontent.com/5043/191365012-9a070faa-b0d6-416c-ada9-e5b964fa82d4.png)
The text was updated successfully, but these errors were encountered: