inertia icon indicating copy to clipboard operation
inertia copied to clipboard

Svelte TypeScript support

Open jakobbouchard opened this issue 1 year ago β€’ 9 comments

This PR adds TypeScript support to @inertiajs/svelte (would close #992) as well as some fixes for its useForm helper (same as #1610). This implementation is better than the one in #1135 since the whole code is in TypeScript instead of just using declaration files. Due to using Svelte 4, I had to use TypeScript 5 instead of the same version as the other packages, but since it's compiled anyways, it shouldn't make a difference.

Some notes

  • The build step needs to copy the Svelte components to the dist folder. because they need to be compiled by the same compiler as the rest of the components (that was a fun one to learn).
    • Related to this, Svelte files need to be pre-processed to remove the TypeScript annotations before build. I guess we could technically make 2 versions of the Link component to keep the typings, but I'm unsure how that would work. Maybe it's possible to generate declaration files
  • store.ts has been split into its own bundle, because it needs to be imported both by components and the rest of the code.
  • Since Svelte components can only import ESM modules (I think?), I renamed the ESM modules to .js and the CJS modules to .cjs. Honestly not sure CJS modules are needed, but I left them there anyways just in case.
  • I removed the layout parameter from the store, since it wasn't used anymore (since #529 I think).
  • I took the useForm typings from the @inertiajs/vue3 and adapted them to fit to Svelte. They could be a bit better (mostly for the setStore function, but I don't think it's meant to be used externally?), but they work fine as they are.
  • I disabled verbatimModuleSyntax in tsconfig.json to be consistent with the other packages, but I'd suggest enabling it once the move to TypeScript 5 is done, as I think it provides a much better clarity on what's imported as a type and what is a value.

I haven't tested all functionality extensively yet, but the playground is working. Nothing should really break anyways, as I haven't modified the behaviour of anything. I also finished this late at night, so I may have missed a thing or two!

jakobbouchard avatar Jul 19 '23 07:07 jakobbouchard

I implemented the changes from #1635, and also removed the preprocessing step for svelte components, to keep the types. This requires sveltePreprocess to be added though. If that's a problem, I'll check how to generate .d.ts files for the components instead, but I haven't figured out how to do that yet.

jakobbouchard avatar Aug 11 '23 00:08 jakobbouchard

@jakobbouchard did you by any chance stumbled on #1621? I was trying to fix it, but was not able to find a root of the issue. Seems like in Svelte 4 something changed about how reactivity works, so that nested layouts doesn't work correctly anymore and stores not being updated.

The issue is quite critical, it's not ok that it was closed.

punyflash avatar Aug 15 '23 13:08 punyflash

@punyflash I could check if I can reproduce it next week. I made this PR for a future project honestly, so I haven't really messed with inertia much yet.

jakobbouchard avatar Aug 17 '23 10:08 jakobbouchard

@jakobbouchard Hey thanks so much for this contribution β€” I'd love to get the Svelte adapter on TypeScript, since all the other adapters are already. You might just have to give me a bit to properly review and test this PR πŸ‘

reinink avatar Aug 17 '23 13:08 reinink

πŸ‘‹ Hi everyone! I'd love this for a project I'm currently working on too. Is there anything I can do to help move it across the finish line? Testing, rebasing, review?

bholtbholt avatar Oct 10 '23 00:10 bholtbholt

Probably some testing to be done for sure, I haven't looked into this for a while. I'm also unsure if I'm building the components/types correctly, so if anyone with more experience could review that, that'd be good!

jakobbouchard avatar Oct 14 '23 01:10 jakobbouchard

@jakobbouchard I've wrote Inertia + Svelte template using this PR https://github.com/kent013/laravel-vite-svelte-spa-template

When I simply imported page from @inertiajs/svelte causes an error

<script lang="ts">
  import { Link, page } from '@inertiajs/svelte'
</script>
{#if $page.props.auth.user} 
                ^^^^^ '$page.props.auth' is of type 'unknown'.ts(18046)

to resolve this error needs some tricky type definition to remove the error

https://github.com/kent013/laravel-vite-svelte-spa-template/blob/main/resources/js/inertia.ts

import type { Page, PageProps } from '@inertiajs/core'
import { page as originalPage } from '@inertiajs/svelte'
import type { Readable } from 'svelte/motion'

export interface User {
  id: number
  name: string
  email: string
  email_verified_at: string
}

export interface SharedProps extends PageProps {
  auth: { user: User }
}

const page: Readable<Page<SharedProps>> = originalPage as unknown as Readable<Page<SharedProps>>

export { page }

But I don't know that this is right way to solve this problem. Perhaps there is a more cleaner way to do it or am simply doing odd.

Just a report, thanks.

kent013 avatar Oct 22 '23 22:10 kent013

@kent013 yeah, I'm unsure of the best way to generate types. Maybe there's someone who's more experienced at Svelte than I who could help here.

jakobbouchard avatar Oct 23 '23 23:10 jakobbouchard

@kent013 this is what I'm using for types and it's working very well:

declare module "@inertiajs/svelte" {
  import { Page } from "@inertiajs/core";
  import { Readable } from "svelte/store";

  // these are where your custom $page.props.* go
  interface ApplicationProps {
    user: User; // for example
  }

  // combines your custom props with the defaults Intertia already has
  interface ApplicationPage extends Readable<Page> {
    props: Page["props"] & ApplicationProps;
  }

  // redefines Inertia's page with your combined page
  export const page: Readable<ApplicationPage>;
}

Very close it what you already have with a couple tweaks to get types working.

bholtbholt avatar Oct 27 '23 01:10 bholtbholt

Hey @jakobbouchard! Coming back to this PR, and just wanted to say that I'd love to still get Svelte TypeScript support added to Inertia. Are you still at all interested in helping out on this? I've been chatting with @punyflash and @pedroborges, and they're both willing to help out as well on this adapter, so hopefully between us all we can make this happen β€”Β let me know if you're interested still? Thanks so much again for your original work here πŸ™

reinink avatar Apr 17 '24 11:04 reinink

If this stales, I'll create a new PR on weekends, I already have working implementation, but would be sad losing your contribution, @jakobbouchard. If you can rebase your PR, I'll be glad to add changes on top of your initial code.

punyflash avatar Apr 17 '24 14:04 punyflash

Hey! I can try rebasing sometimes this weekend and update you then. I just started a new job in game development, so I haven't touched this in a while now, but I'd be glad to help still!

jakobbouchard avatar Apr 17 '24 21:04 jakobbouchard

@punyflash @jakobbouchard wonderful, thanks so much!

reinink avatar Apr 18 '24 11:04 reinink