Comments (16)
This is likely very close to the stuff I was investigating here. You can't easily influence how TS infers such things.
You could use NoInfer
to get the desired behavior here (TS playground) but you don't really want this because that will prevent json
from "working on its own".
The essence here is likely something around those lines: the contextual return type is a lower priority inference and an inference made directly from the arguments will always "win" over it.
from msw.
But this would still work, would it not?
Yes.
from msw.
You only need to wrap T
and nothing else: TS playground
from msw.
Hi, @Hajime-san. Thanks for this suggestion, I think it makes perfect sense.
A bit of context why it allows additional fields right now. Since the response body type is provided onto the handler itself, there's no way to "drill" it to the argument type of HttpResponse.json()
. Instead, what happens is this:
export const handlers = [
handleSdkRequest(async ({ request }) => {
const data = await request.json()
// Body type is inferred from the argument you provide
// to the HttpResponse.json().
return HttpResponse.json({
transactionId: data.transactionId,
// `bar` should be error
data: { ok: true, foo: 'bar' },
})
}),
]
The inferred body type becomes this:
HttpResponse.json<{ transactionId, data: { ok, foo } }>
This type is later compared to the return type of the entire resolver, which is inferred from your response body type argument (the narrow type). It seems, since it matches partially, it passes the validation.
Reproduction
Here's this issue distilled to a minimal reproduction scenario outside of MSW:
from msw.
Alas, NoInfer
has been introduced only in v5.4. Sigh.
I don't support one can check if a built-in type exists before using it.
@Hajime-san, it looks like there's no capabilities in TypeScript to achieve what you want (see a fantastic explanation). You have one option: provide an explicit response body type to HttpResponse.json<HERE>()
.
from msw.
Are there any other implications to using NoInfer?
you'd break the simplest things like
const j = json({ foo: 'bar'})
return j
So it could lead to surprising DX.
Alas, NoInfer has been introduced only in v5.4. Sigh.
Right. You can mimic it using this though:
type NoInfer<T> = [T][T extends any ? 0 : never]
from msw.
Thank you for implementing this feature!
from msw.
Note that if you provide the narrow response body type to HttpResponse.json<*>()
, you will get the behavior you want:
return HttpResponse.json<SdkResponse>({ ... })
Playground showcasing the "unknown property 'bar'" type error.
Since HttpResponse
is imported separately from the response resolver, I don't believe there's a way for the resolver to "forward" that response body type onto the HttpResponse.json()
call. The body argument type will always be inferred, and if it matches with extra properties, that will satisfy the type in TypeScript's eyes:
Lines 79 to 82 in 16fadfe
from msw.
@Andarist, please, correct me if I'm wrong, Mateusz.
from msw.
https://twitter.com/TitianCernicova/status/1770789543509168365
from msw.
@Andarist, but this case is a bit different, isn't it? I can clearly get a proper narrow type if I provide an explicit body generic. The problem is not how the response body type is declared but how to project that type onto the HttpResponse.json()
function's argument.
// Works if the body type is explicitly provided.
// Hijacks inference from the argument value.
+return json<ResponseBodyType>({ foo: true, bar: 'xyz' })
// Breaks because now the T in json<T> gets inferred from
// a broader value and it satisfies the type.
-return json({ foo: true, bar: 'xyz' })
I get your point that a broader type satisfying a narrower type is how types work. I was mostly curious if we can make this type projection possible? Because in this case it does feel like a bug to the user.
from msw.
You could use NoInfer to get the desired behavior
TIL NoInfer
. This makes me consider if HttpResponse.json()
has a use on its own. I'm tempted to say it doesn't. You can certainly use it to construct a Response anywhere you wish but it's designed to work with response resolvers (hence the magic with the strict body type) so it may be reasonable to get StrictResponse<unknown>
unless you (a) put it in a typed resolver; (b) provide the body type explicitly as json<T>
.
Are there any other implications to using NoInfer
?
from msw.
you'd break the simplest things like
But this would still work, would it not?
const j = json<T>(value)
return j // StrictResponse<T>
I'd say it's fine to have StrictResponse<unknown>
if you haven't provided an explicit generic. That even makes sense. I wonder if we can replace unknown
here with DefaultBodyType
since we, technically, know the constraints of the response bodies transferred over the network.
from msw.
@Andarist, I'm trying your suggestion but not getting the same behavior for custom NoInfer
. Is something off, in your opinion?
from msw.
I'm implementing this in #2107. I think this is a good direction to follow.
from msw.
Released: v2.2.11 🎉
This has been released in v2.2.11!
Make sure to always update to the latest version (npm i msw@latest
) to get the newest features and bug fixes.
Predictable release automation by @ossjs/release.
from msw.
Related Issues (20)
- Error: No known conditions for "./browser" specifier in "msw" package HOT 5
- "Cannot read properties of undefined (reading 'get')" when using generators/async generators as resolvers HOT 2
- `TypeError: crypto.randomUUID is not a function` with msw 2.2.12 HOT 3
- When running Cypress tests in Electron, MSW activation occurs after test completion, causing tests to fail
- Chrome unregisters MSW after 5 mins of inactivity / idle HOT 13
- First-class Server-Sent Events (SSE) API
- The currently registered Service Worker has been generated by a different version of MSW (undefined) HOT 1
- disable prettier as well HOT 1
- Issue with response resolver types after recent upgrade HOT 2
- "TypeError: response.body.getReader is not a function" for HTTPResponse of JSON type HOT 5
- Preserve the original request URL in "onUnhandledRequest" warnings HOT 3
- The cookies object recevied in the handlers varies depending on the placement of the handler within the `setupServer` function. HOT 5
- Calls to worker.use() remove handlers to same endpoint with different method HOT 1
- Unable to use HttpResponse.error() with TypeScript HOT 3
- How do I implement MSW in a NextJS backend?
- Missing `await` in the getting started example section for fetch call HOT 4
- 'Cannot read properties of undefined (reading 'url')' when multiple browser tabs are open
- Question: Should we use msw to mock server-side apis based on the request body? HOT 1
- Update Documentation to Include undici Compatibility Issues and Solutions HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from msw.