sveltejs / sveltejs/kit

Make App.d.ts route id aware

Open
#11,925 6 comments 7 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
20.8k
Forks
2.3k
Avg merge
1d 16h
Merged PRs (30d)
156

Description

Describe the problem

Defining globals for PageData is fine for most of the time. But when you are splitting your app in 2 or more named layouts with with specific data being loaded in +layout.ts / +layout.server.ts it's frustrating to have to force non-null checking for data that will always be there.

For example:

declare global {
	namespace App {
		/** Local data populated by Handle hook */
		interface Locals
		{
			prisma: PrismaClient;
			s3: S3Client;
			
			user: User | null;
			session: Session | null;

			appSettings?: AppSettings; // this is never populated in /install route
			userSettings?: UserSettings; // this is never populated in /install route
		}
	
		/** Page data populated by layouts load function */
		interface PageData
		{
			user: User | null;
			session: Session | null;
			
			appSettings?: AppSettings // this is never populated in /install route
			userSettings?: UserSettings // this is never populated in /install route
		}
	}
}

Leads to having ESLint being completely lost here, as data is there but typed as optional.

Capture d’écran 2024-03-01 à 09 36 54
Describe the proposed solution

The actual way of defining global app types should not be modified as it works fine for almost everyone. We could add something like:

declare global {

	namespace App {

		// interface Error {}
		// interface Platform {}
                 // interface PageData {} This becomes useless as it is filled with context types

		/** Local data populated by Handle hook */
		interface Locals
		{
			prisma: PrismaClient;
			s3: S3Client;
		}
		
		/** 
		 * Define fine grained types based on route context. 
		 * Routes inherits global types and their corresponding context types 
		 */
		interface Context {

			/** 
                           * Define data based on route context 
                           * `/app/*` would match all routes that begins with /app
                           */
			[`/app/*`] :  {

				locals: {
					appSettings: AppSettings;
					userSettings: UserSettings;
					user: User;
					session: Session;
				}

				pageData: {
					user: User;
					session: Session;
					appSettings: AppSettings;
					userSettings: UserSettings;
				}
			}
		}
	}
}
Alternatives considered

As stated in the docs Use optional properties for data that is only present on specific pages. works fine tbh, juste let ESLint scream at you and be confident about your data structure.

Importance

would make my life easier

Additional Information

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the proposed App.Context declaration alongside the existing App.d.ts typing behavior and the +layout.ts / +layout.server.ts route data model. Trace how route context types are generated and inherited, then identify the relevant type-generation tests. Done means route-specific locals and page data are inferred without requiring optional properties globally, while existing global App types continue to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
developer-experience
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.