- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 2.1k
          feat: typed +server.ts responses with fetch
          #11108
        
          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
Conversation
| 
 | 
| For typing request  interface TypedRequest<T = any> {
    json(): Promise<T>
}
interface TypedEvent<T = any> {
    request: TypedRequest<T>
}
export async function GET({ request }: TypedEvent<{ foo: string }>) {
    let { foo } = await request.json()
}Not sure if there's an easier way to do this, but it feels a lot more explicit than doing let { foo } = await request.json() as { foo: string } | 
| Hi, after considering both my proposal in #9938 and yours here my opinion is a little divided. I believe that SvelteKit's mission to make everything accessible to new users, simple to use and implicitly typed is very important. I liked the way my proposal handles things, because it was a change that everyone could benefit from without changing a single line of code. Though it turned out to be a pain to manage, with extremely complicated Types and trouble overall to represent all the possible fetch cases with one or two overloads. I also like your proposal which feels a lot natural and leads to code similar to tRPC without requiring a lot of code changes. My only worry is introducing a function like api_fetch which is basically identical to fetch in its behaviour, but exists with the sole purpose of enforcing types on request (body and path) and on the response. I really liked the simplicity of using the same fetch function for everything. In an ideal world I would choose the typed fetch function (my proposal), but from a user perspective of understanding errors and the types behind the function it is very complicated, and even more complicated is to maintain it in the future. Overall yours seems the most feasible one. How about redirect and goto functions? Should they be rewritten too in the same way? Maybe for fetch, redirect and goto we could provide the base function for non relative paths (ex. Https://...) While for root relative paths (/...) we could provide your api_fetch with the path parameters in the request by overloading the base fetch function. And the same goes for redirect and goto. | 
| Is this going to be accepted eventually? Can we not just roll the behaviour of the would be 'api-fetch' into the standard sveltekit fetch? It already has special behaviours (as when allowing local routes to autocomplete to the full route). | 
| 
 Yes I believe it would be possible to roll the behavior into the standard sveltekit  
 Yes, I believe it would be possible to support this as well, to ensure that goto's and redirects are valid. Additionally this change should be backwards compatible, and it will still be possible to manually call the API routes with no typing/params provided in the API call With fetch, the pseudo algorithm could work similarly to this It should be also possible to import the svelte custom fetch into the context of components too | 
| @Rich-Harris thoughts on this proposal? | 
| feels like this is would be the last major addition to make a sveltekit project fully typesafe all around, especially with the new typesafety in component markup with svelte 5.0 big fan of this 👍 | 
| I would like to add my support here, I am fan of this proposal over #9938, I think the extra complexity is worthwhile to get a more tRPC like experience. | 
| 
 The typing in that becomes hell as the author mentioned because typescript doesn't have Regex types. 
 It just makes sense to use URLs that match the path templates of pages and then using a  export async function load({ fetch }) {
    const data = await fetch("/api/[post]", {
        method: "GET",
        params: { post: "123" }
    });
    return {
        text: data.post_id // typed as a string
    }
}would be functionally equivalent to this (minus the types) export async function load({ fetch }) {
    const data = await fetch("/api/123", {
        method: "GET"
    });
    return {
        text: data.post_id // untyped
    }
} | 
| Something like this should be possible to achieve via this approach, here I am using Zod library as an example for input validation 
 import { z } from "zod"
const api_inputs = z.object({
   foo: z.string()
})
export async function POST(
  { request }: TypedEvent<z.infer<typeof api_inputs>>
) { // function return type inferred
   const data = api_inputs.parse(await request.json()) // typed & validated input
   
   return json({
      baz: "bar"
   }) // return type validated as TypedResponse<{ baz: "bar" }>
}
 let res = await fetch("/api/xyz", {
   method: "POST",
   body: {
     foo: "hello world"
   } // this body would be type-checked
}) // TypedResponse<{ baz: "bar"}>
const data = await res.json() //  typed as { baz: "bar" } | 
| In favor of making this the default behavior of  | 
+server.ts responses with fetch+server.ts responses with fetch
      | @PuruVJ I'm not so sure that this is actually a breaking change. We would want to create a  The  | 
| Understand the team is likely very busy with Svelte 5 RC stuff, but would love to get this merged! Are there any further blockers? | 
| @hmnd yeah, very little is developed in terms of the actual PR, but I think there's a solid theoretical direction for where to go. Might need some help figuring out how we want to structure this in the code, and the right modules i'll need to modify to get this system implemented 
 | 
| Some additional benefits/advantages to this is that: 
 | 
| does this work in client side too like in event bindings? | 
| 
 Could you elaborate? Edit If you mean like a  | 
| 
 yes. that's what i meant. nice. | 
| any updates on this ticket guys? | 
| @mingsterism I might continue work on this in the near future. I've got some good ideas for further enhancing the proposal too | 
| This would be nice to have | 
| Thank you all, but hopefully now that remote functions are available it's clear why we didn't end up going down this route — the best way to get type safety is to treat  | 
Attempting to solve
+server.tstypes for API calling #11101+server.tstypes for API calling #11101Approach
/api/[post]/+server.tsutils+page.ts+page.svelteTheory
Using function overloading in typescript we can overload the
fetchor custom fetch method with type info that gives us information about available APIs, return types and parameters.This system could also be extended to provide typed inputs for the
bodyparameter infetchas well as supporting typedgotosredirects and moreThe custom
fetchprovided in theloadfunctions and other places would more or less reflect the structure of the nativefetchexcept with a few changes:paramsRequestInitproperties are overrided to force things such asmethod: "GET"as well as providing an additional parameter calledparamsexampleProof of concept example
I am posting this as a draft PR to gain feedback from the community and contributors.
Some unresolved matters:
App.Errorsomewhere?)Related PRs