inertia
inertia copied to clipboard
Svelte TypeScript support
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
- 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
-
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 thesetStore
function, but I don't think it's meant to be used externally?), but they work fine as they are. - I disabled
verbatimModuleSyntax
intsconfig.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!
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 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 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 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 π
π 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?
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 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 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.
@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.
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 π
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.
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!
@punyflash @jakobbouchard wonderful, thanks so much!