Closed nurdism closed 1 year ago
I managed to override this by re-declaring + re-exporting the whole function, as it isn't an interface:
import { router } from '@inertiajs/vue3'
declare module '@inertiajs/vue3' {
export declare const router: router
export declare function usePage<Props> (): {
component: string;
props: Props & {
errors?: import('@inertiajs/core').Errors & import('@inertiajs/core').ErrorBag;
};
url: string;
version?: string;
scrollRegions?: {
top: number;
left: number;
}[];
rememberedState?: Record<string, unknown>;
resolvedErrors?: import('@inertiajs/core').Errors;
}
}
Just out of interest, was there a particular reason the generic type argument was removed from the usePage
function? I used to be able to type the props with usePage<SomePropsInterface>
, but now I need to use page.props as unknown as SomePropsInterface
, which doesn't look particularly neat...
Similarly, the useForm
extends Record<string, unknown>
, which causes some type errors if I have an interface with optional keys for example... I managed to fix this by re-exporting those functions too:
function useForm<TForm = Record<string, unknown>> (data: TForm): InertiaForm<TForm>
export default function useForm<TForm = Record<string, unknown>> (rememberKey: string, data: TForm): InertiaForm<TForm>
I have also come up with a solution to this by re-exporting, like so:
globals.d.ts
import type { Page } from '@inertiajs/core'
declare module '@inertiajs/vue3' {
export declare function usePage<T>(): Page<T>
}
the Page type accepts a generic
Ah, perfect, that's a much nicer solution! Thanks @nurdism
export declare function usePage
(): Page
I'm not sure why, but this was throwing an error for me. I adjusted it and and it seems to be ok with this instead?
import type { Page } from '@inertiajs/core';
declare module '@inertiajs/vue3' {
export function usePage<T>(): Page<T>
}
export declare function usePage(): Page
I'm not sure why, but this was throwing an error for me. I adjusted it and and it seems to be ok with this instead?
import type { Page } from '@inertiajs/core'; declare module '@inertiajs/vue3' { export function usePage<T>(): Page<T> }
This worked like a charm for me, and I combine it with my own definition for the props, like so:
import type { Page, PageProps } from '@inertiajs/core';
declare module '@inertiajs/vue3' {
export function usePage<T>(): Page<T>;
}
declare global {
export interface InertiaProps extends Page<PageProps> {
flashNotifications: Array<App.FlashNotification>;
}
}
And then you can use it like so:
const notifications = computed(() => usePage<InertiaProps>().props.flashNotifications);
And get full autocompletion for props.
I'm not a typescript expert, maybe there is a better way of doing this, please let me know, but it works like a charm.
declare module '@inertiajs/core' {
interface PageProps { // you can define global $page/usePage() props by extending/defining this interface
myGlobalProp: string[]
}
}
declare module '@inertiajs/vue3' {
export function usePage<T>(): Page<T> // the T generic will combine any type you add to it & the PageProps interface defined in @inertiajs/core
}
const page = usePage<{ myLocalProp: string }>() // the types for page.props should be { myGlobalProp: string[]; myLocalProp: string }
const page = usePage() // the types for page.props should be { myGlobalProp: string[]; }
declare module '@inertiajs/vue3' { export function usePage<T>(): Page<T> // the T generic will combine any type you add to it & the PageProps interface defined in @inertiajs/core }
You just blew my mind, thank you! Much, much cleaner.
This worked like a charm for me, and I combine it with my own definition for the props, like so:
I use it slightly differently than your example. Seems to work fine:
import type { Page } from '@inertiajs/core';
declare module '@inertiajs/vue3' {
export function usePage<T>(): Page<T>
}
interface GlobalProps extends Page {
meta: {
user: LoggedInUser
},
flash: {
message: string | null,
error: string | null
}
}
interface ManageUserPageProps extends GlobalProps {
user: FullUser
available_roles: Role[]
available_permissions: string[]
}
I shove all my page prop definitions into that file. Then, in my vue files:
const available_roles = usePage<ManageUserPageProps>().props.available_roles;
Seems to work fine.
Just out of interest, was there a particular reason the generic type argument was removed from the
usePage
function? I used to be able to type the props withusePage<SomePropsInterface>
, but now I need to usepage.props as unknown as SomePropsInterface
, which doesn't look particularly neat...
I forgot to copy that definition from the old type definitions when converting the adapters to TypeScript, so they were just inferred without the generic.
I've created https://github.com/inertiajs/inertia/pull/1394 that attempts to address this; however, I can't currently get it to build.
import type { Page } from '@inertiajs/core';
declare module '@inertiajs/vue3' {
export function usePage<T extends PageProps>() : Page<T>
}
I've been trying to work with typing usePage()
using PNPM. Has anyone had any luck with that? With PNPM you can't import types from @inertiajs/core
since it's a child dependency of @inertiajs/vue3
and not a direct project-level dependency.
Separately installing @inertiajs/core
as a project dependency would be possible, but it seems like a bad idea as you'd need to separately manage the versions of these two packages instead of just letting @inertiajs/vue3
keep track of the versions on its own.
Is there a way to type usePage()
without also adding @inertiajs/core
as a project-level dependency?
Here's what works great if you can import from @inertiajs/core
(which works fine with NPM). This updated the definition of usePage
everywhere so you don't have to manually type it each time:
SharedProps.d.ts
import type User from "@/Types/Models/User";
import type { Page, PageProps } from "@inertiajs/core";
interface SharedProps extends PageProps {
auth: {
user: User;
};
}
export default SharedProps;
declare module "@inertiajs/vue3" {
export function usePage(): Page<SharedProps>;
}
The solution below sort of works with PNPM, but it less convenient because you have to manually type every instance of usePage
. The [key: string]: any
bit also seems like it isn't a good idea, but seems to be necessary:
SharedProps.d.ts
import type User from "@/Types/Models/User";
interface SharedProps{
auth: {
user: User;
};
[key: string]: any;
}
export default SharedProps;
const page = usePage<SharedProps>();
import type User from "@/Types/Models/User";
import type { Page, PageProps } from "@inertiajs/core";
interface SharedProps extends PageProps {
auth: {
user: User;
};
}
export default SharedProps;
declare module "@inertiajs/vue3" {
export function usePage(): Page<SharedProps>;
}
thanks @Smef, it works on me
I've been trying to work with typing
usePage()
using PNPM. Has anyone had any luck with that? With PNPM you can't import types from@inertiajs/core
since it's a child dependency of@inertiajs/vue3
and not a direct project-level dependency.Separately installing
@inertiajs/core
as a project dependency would be possible, but it seems like a bad idea as you'd need to separately manage the versions of these two packages instead of just letting@inertiajs/vue3
keep track of the versions on its own.Is there a way to type
usePage()
without also adding@inertiajs/core
as a project-level dependency?
@Smef @rikarani
Solution for when working with pnpm that I figured out
public-hoist-pattern[]=@inertiajs/core
pnpm install
Version:
@inertiajs/vue3
version: 1.0.0Describe the problem:
@inertiajs/vue3/types/app.d.ts@usePage
types are declared asit does not inherit from the
Page
type from@inertiajs/core
and it causing all instances ofusePage()
to ignore thePageProps
interface in@inertiajs/core/types/types.ts
if extending the
PageProps
interface viait does not reflect in
usePage()
typings