diff --git a/.changeset/friendly-pears-wash.md b/.changeset/friendly-pears-wash.md new file mode 100644 index 000000000000..d407b01f4833 --- /dev/null +++ b/.changeset/friendly-pears-wash.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +[fix] better type generation for load functions with different return values diff --git a/packages/kit/src/core/sync/write_types/index.js b/packages/kit/src/core/sync/write_types/index.js index e9676711de03..fb442c41c6c0 100644 --- a/packages/kit/src/core/sync/write_types/index.js +++ b/packages/kit/src/core/sync/write_types/index.js @@ -215,6 +215,11 @@ function update_types(config, routes, route, to_delete = new Set()) { ); // null & {} == null, we need to prevent that in some situations declarations.push(`type EnsureDefined = T extends null | undefined ? {} : T;`); + // Takes a union type and returns a union type where each type also has all properties + // of all possible types (typed as undefined), making accessing them more ergonomic + declarations.push( + `type OptionalUnion, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude]?: never } & U : never;` + ); } if (route.leaf) { @@ -402,7 +407,7 @@ function process_node(node, outdir, is_page, proxies, all_pages_have_load = true proxy ); - data = `Expand & EnsureDefined<${type}>>`; + data = `Expand & OptionalUnion>>`; const output_data_shape = !is_page && all_pages_have_load @@ -438,7 +443,7 @@ function process_node(node, outdir, is_page, proxies, all_pages_have_load = true ? `./proxy${replace_ext_with_js(path.basename(file_path))}` : path_to_original(outdir, file_path); const type = `Kit.AwaitedProperties>>`; - return expand ? `Expand<${type}>` : type; + return expand ? `Expand>>` : type; } else { return fallback; } diff --git a/packages/kit/src/core/sync/write_types/index.spec.js b/packages/kit/src/core/sync/write_types/index.spec.js index 3385f7228333..41f696fc6e47 100644 --- a/packages/kit/src/core/sync/write_types/index.spec.js +++ b/packages/kit/src/core/sync/write_types/index.spec.js @@ -1,35 +1,19 @@ -// @ts-nocheck import path from 'path'; -import fs from 'fs'; -import { format } from 'prettier'; import { fileURLToPath } from 'url'; import { test } from 'uvu'; import * as assert from 'uvu/assert'; -import { rimraf, walk } from '../../../utils/filesystem.js'; +import { rimraf } from '../../../utils/filesystem.js'; import options from '../../config/options.js'; import create_manifest_data from '../create_manifest_data/index.js'; import { tweak_types, write_all_types } from './index.js'; +import { execSync } from 'child_process'; const cwd = fileURLToPath(new URL('./test', import.meta.url)); -function format_dts(file) { - // format with the same settings we use in this monorepo so - // the output is the same as visible when opening the $types.d.ts - // files in the editor - return format(fs.readFileSync(file, 'utf-8'), { - parser: 'typescript', - useTabs: true, - singleQuote: true, - trailingComma: 'none', - printWidth: 100 - }); -} - /** * @param {string} dir - * @param {(code: string) => string} [prepare_expected] */ -async function run_test(dir, prepare_expected = (code) => code) { +async function run_test(dir) { rimraf(path.join(cwd, dir, '.svelte-kit')); const initial = options({}, 'config'); @@ -43,66 +27,25 @@ async function run_test(dir, prepare_expected = (code) => code) { config: /** @type {import('types').ValidatedConfig} */ (initial) }); await write_all_types(initial, manifest); - - const expected_dir = path.join(cwd, dir, '_expected'); - const expected_files = walk(expected_dir, true); - const actual_dir = path.join( - path.join(cwd, dir, '.svelte-kit', 'types'), - path.relative(process.cwd(), path.join(cwd, dir)) - ); - const actual_files = walk(actual_dir, true); - - assert.equal(actual_files, expected_files); - - for (const file of actual_files) { - const expected_file = path.join(expected_dir, file); - const actual_file = path.join(actual_dir, file); - if (fs.statSync(path.join(actual_dir, file)).isDirectory()) { - assert.ok(fs.statSync(actual_file).isDirectory(), 'Expected a directory'); - continue; - } - - const expected = format_dts(expected_file); - const actual = format_dts(actual_file); - const err_msg = `Expected equal file contents for ${file} in ${dir}`; - assert.fixture(actual, prepare_expected(expected), err_msg); - } } -test('Create $types for +page.js', async () => { +test('Creates correct $types', async () => { + // To safe us from creating a real SvelteKit project for each of the tests, + // we first run the type generation directly for each test case, and then + // call `tsc` to check that the generated types are valid. await run_test('simple-page-shared-only'); -}); - -test('Create $types for page.server.js', async () => { await run_test('simple-page-server-only'); -}); - -test('Create $types for page(.server).js', async () => { await run_test('simple-page-server-and-shared'); -}); - -test('Create $types for layout and page', async () => { await run_test('layout'); -}); - -test('Create $types for grouped layout and page', async () => { await run_test('layout-advanced'); -}); - -test('Create $types with params', async () => { - await run_test('slugs', (code) => - // For some reason, the order of the params differentiates between windows and mac/linux - process.platform === 'win32' - ? code.replace( - 'rest?: string; slug?: string; optional?: string', - 'optional?: string; rest?: string; slug?: string' - ) - : code - ); -}); - -test('Create $types with params and required return types for layout', async () => { + await run_test('slugs'); await run_test('slugs-layout-not-all-pages-have-load'); + try { + execSync('pnpm testtypes', { cwd }); + } catch (e) { + console.error(/** @type {any} */ (e).stdout.toString()); + throw new Error('Type tests failed'); + } }); test('Rewrites types for a TypeScript module', () => { diff --git a/packages/kit/src/core/sync/write_types/test/layout-advanced/(main)/+page.js b/packages/kit/src/core/sync/write_types/test/layout-advanced/(main)/+page.js index 5fe08cbda75c..2368bd47160f 100644 --- a/packages/kit/src/core/sync/write_types/test/layout-advanced/(main)/+page.js +++ b/packages/kit/src/core/sync/write_types/test/layout-advanced/(main)/+page.js @@ -1 +1,9 @@ // test to see if layout adjusts correctly if +page.js exists, but no load function + +/** @type {import('../.svelte-kit/types/src/core/sync/write_types/test/layout-advanced/(main)/$types').PageData} */ +const data = { + root: '' +}; +data.root; +// @ts-expect-error +data.main; diff --git a/packages/kit/src/core/sync/write_types/test/layout-advanced/(main)/sub/+page.js b/packages/kit/src/core/sync/write_types/test/layout-advanced/(main)/sub/+page.js index f798381b7b93..908adae6e5df 100644 --- a/packages/kit/src/core/sync/write_types/test/layout-advanced/(main)/sub/+page.js +++ b/packages/kit/src/core/sync/write_types/test/layout-advanced/(main)/sub/+page.js @@ -1,5 +1,21 @@ -export function load() { +/** @type {import('../../.svelte-kit/types/src/core/sync/write_types/test/layout-advanced/(main)/sub/$types').PageLoad} */ +export async function load({ parent }) { + const p = await parent(); + p.main; + p.root; + // @ts-expect-error + p.sub; return { sub: 'sub' }; } + +/** @type {import('../../.svelte-kit/types/src/core/sync/write_types/test/layout-advanced/(main)/sub/$types').PageData} */ +const data = { + main: '', + root: '', + sub: '' +}; +data.main; +data.root; +data.sub; diff --git a/packages/kit/src/core/sync/write_types/test/layout-advanced/_expected/$types.d.ts b/packages/kit/src/core/sync/write_types/test/layout-advanced/_expected/$types.d.ts deleted file mode 100644 index adb1faace99e..000000000000 --- a/packages/kit/src/core/sync/write_types/test/layout-advanced/_expected/$types.d.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = {}; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type LayoutParams = RouteParams & {}; -type LayoutParentData = EnsureDefined<{}>; - -export type LayoutServerData = null; -export type LayoutLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.Load; -export type LayoutLoadEvent = Parameters[0]; -export type LayoutData = Expand< - Omit< - LayoutParentData, - keyof Kit.AwaitedProperties< - Awaited> - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited> - > - > ->; diff --git a/packages/kit/src/core/sync/write_types/test/layout-advanced/_expected/(main)/$types.d.ts b/packages/kit/src/core/sync/write_types/test/layout-advanced/_expected/(main)/$types.d.ts deleted file mode 100644 index b37d2bb416bc..000000000000 --- a/packages/kit/src/core/sync/write_types/test/layout-advanced/_expected/(main)/$types.d.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = {}; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type PageParentData = EnsureDefined; -type LayoutParams = RouteParams & {}; -type LayoutServerParentData = EnsureDefined; -type LayoutParentData = EnsureDefined; - -export type PageServerData = null; -export type PageLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.Load; -export type PageLoadEvent = Parameters[0]; -export type PageData = Expand< - Omit> & - EnsureDefined> ->; -export type LayoutServerLoad< - OutputData extends (Partial & Record) | void = - | (Partial & Record) - | void -> = Kit.ServerLoad; -export type LayoutServerLoadEvent = Parameters[0]; -export type LayoutServerData = Expand< - Kit.AwaitedProperties< - Awaited> - > ->; -export type LayoutData = Expand< - Omit & EnsureDefined ->; -export type RequestEvent = Kit.RequestEvent; diff --git a/packages/kit/src/core/sync/write_types/test/layout-advanced/_expected/(main)/sub/$types.d.ts b/packages/kit/src/core/sync/write_types/test/layout-advanced/_expected/(main)/sub/$types.d.ts deleted file mode 100644 index 6d3a147d3033..000000000000 --- a/packages/kit/src/core/sync/write_types/test/layout-advanced/_expected/(main)/sub/$types.d.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = {}; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type PageParentData = Omit< - EnsureDefined, - keyof import('../$types.js').LayoutData -> & - EnsureDefined; - -export type PageServerData = null; -export type PageLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.Load; -export type PageLoadEvent = Parameters[0]; -export type PageData = Expand< - Omit< - PageParentData, - keyof Kit.AwaitedProperties< - Awaited> - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited> - > - > ->; diff --git a/packages/kit/src/core/sync/write_types/test/layout/+layout.js b/packages/kit/src/core/sync/write_types/test/layout/+layout.js index 3b51904671c5..c8bc95024f98 100644 --- a/packages/kit/src/core/sync/write_types/test/layout/+layout.js +++ b/packages/kit/src/core/sync/write_types/test/layout/+layout.js @@ -1,4 +1,8 @@ -export function load() { +/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/layout/$types').LayoutLoad} */ +export function load({ data }) { + data.server; + // @ts-expect-error + data.shared; return { shared: 'shared' }; diff --git a/packages/kit/src/core/sync/write_types/test/layout/+layout.server.js b/packages/kit/src/core/sync/write_types/test/layout/+layout.server.js index 2d7f37001f6a..77a2a9780b5b 100644 --- a/packages/kit/src/core/sync/write_types/test/layout/+layout.server.js +++ b/packages/kit/src/core/sync/write_types/test/layout/+layout.server.js @@ -1,3 +1,4 @@ +/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/layout/$types').LayoutServerLoad} */ export function load() { return { server: 'server' diff --git a/packages/kit/src/core/sync/write_types/test/layout/+page.js b/packages/kit/src/core/sync/write_types/test/layout/+page.js index 2abb61fe6db1..4abd01995480 100644 --- a/packages/kit/src/core/sync/write_types/test/layout/+page.js +++ b/packages/kit/src/core/sync/write_types/test/layout/+page.js @@ -1,5 +1,17 @@ -export function load() { +/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/layout/$types').PageLoad} */ +export function load({ data }) { + data.pageServer; + // @ts-expect-error + data.pageShared; return { pageShared: 'pageShared' }; } + +/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/layout/$types').PageData} */ +const data = { + shared: 'asd', + pageShared: 'asd' +}; +data.shared; +data.pageShared; diff --git a/packages/kit/src/core/sync/write_types/test/layout/_expected/$types.d.ts b/packages/kit/src/core/sync/write_types/test/layout/_expected/$types.d.ts deleted file mode 100644 index 7aa6216adc85..000000000000 --- a/packages/kit/src/core/sync/write_types/test/layout/_expected/$types.d.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = {}; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type PageServerParentData = EnsureDefined; -type PageParentData = EnsureDefined; -type LayoutParams = RouteParams & {}; -type LayoutServerParentData = EnsureDefined<{}>; -type LayoutParentData = EnsureDefined<{}>; - -export type PageServerLoad< - OutputData extends (Partial & Record) | void = - | (Partial & Record) - | void -> = Kit.ServerLoad; -export type PageServerLoadEvent = Parameters[0]; -export type ActionData = unknown; -export type PageServerData = Expand< - Kit.AwaitedProperties< - Awaited> - > ->; -export type PageLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.Load; -export type PageLoadEvent = Parameters[0]; -export type PageData = Expand< - Omit< - PageParentData, - keyof Kit.AwaitedProperties< - Awaited> - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited> - > - > ->; -export type Action = Kit.Action; -export type Actions = Kit.Actions; -export type LayoutServerLoad< - OutputData extends (Partial & Record) | void = - | (Partial & Record) - | void -> = Kit.ServerLoad; -export type LayoutServerLoadEvent = Parameters[0]; -export type LayoutServerData = Expand< - Kit.AwaitedProperties< - Awaited> - > ->; -export type LayoutLoad< - OutputData extends (Partial & Record) | void = - | (Partial & Record) - | void -> = Kit.Load; -export type LayoutLoadEvent = Parameters[0]; -export type LayoutData = Expand< - Omit< - LayoutParentData, - keyof Kit.AwaitedProperties< - Awaited> - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited> - > - > ->; -export type RequestEvent = Kit.RequestEvent; diff --git a/packages/kit/src/core/sync/write_types/test/package.json b/packages/kit/src/core/sync/write_types/test/package.json new file mode 100644 index 000000000000..47d157b4a13a --- /dev/null +++ b/packages/kit/src/core/sync/write_types/test/package.json @@ -0,0 +1,6 @@ +{ + "private": true, + "scripts": { + "testtypes": "tsc" + } +} diff --git a/packages/kit/src/core/sync/write_types/test/simple-page-server-and-shared/+page.js b/packages/kit/src/core/sync/write_types/test/simple-page-server-and-shared/+page.js index 3b51904671c5..9d11e44f0552 100644 --- a/packages/kit/src/core/sync/write_types/test/simple-page-server-and-shared/+page.js +++ b/packages/kit/src/core/sync/write_types/test/simple-page-server-and-shared/+page.js @@ -1,5 +1,17 @@ -export function load() { +/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/simple-page-server-and-shared/$types').PageLoad} */ +export function load({ data }) { + data.server; + // @ts-expect-error + data.shared; return { shared: 'shared' }; } + +/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/simple-page-server-and-shared/$types').PageData} */ +const data = { + shared: 'asd' +}; +data.shared; +// @ts-expect-error +data.server; diff --git a/packages/kit/src/core/sync/write_types/test/simple-page-server-and-shared/_expected/$types.d.ts b/packages/kit/src/core/sync/write_types/test/simple-page-server-and-shared/_expected/$types.d.ts deleted file mode 100644 index e0aa63a0dc77..000000000000 --- a/packages/kit/src/core/sync/write_types/test/simple-page-server-and-shared/_expected/$types.d.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = {}; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type PageServerParentData = EnsureDefined; -type PageParentData = EnsureDefined; -type LayoutParams = RouteParams & {}; -type LayoutParentData = EnsureDefined<{}>; - -export type PageServerLoad< - OutputData extends (Partial & Record) | void = - | (Partial & Record) - | void -> = Kit.ServerLoad; -export type PageServerLoadEvent = Parameters[0]; -export type ActionData = unknown; -export type PageServerData = Expand< - Kit.AwaitedProperties< - Awaited> - > ->; -export type PageLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.Load; -export type PageLoadEvent = Parameters[0]; -export type PageData = Expand< - Omit< - PageParentData, - keyof Kit.AwaitedProperties< - Awaited> - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited> - > - > ->; -export type Action = Kit.Action; -export type Actions = Kit.Actions; -export type LayoutServerData = null; -export type LayoutData = Expand; -export type RequestEvent = Kit.RequestEvent; diff --git a/packages/kit/src/core/sync/write_types/test/simple-page-server-only/+page.server.js b/packages/kit/src/core/sync/write_types/test/simple-page-server-only/+page.server.js index 918efcb130e0..cfdb779689e4 100644 --- a/packages/kit/src/core/sync/write_types/test/simple-page-server-only/+page.server.js +++ b/packages/kit/src/core/sync/write_types/test/simple-page-server-only/+page.server.js @@ -5,5 +5,19 @@ export function load() { } export const actions = { - default: () => ({ foo: 'bar' }) + default: () => ({ action: 'bar' }) }; + +/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/simple-page-server-only/$types').PageData} */ +const data = { + foo: 'asd' +}; +data.foo; +// @ts-expect-error +data.bar; + +/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/simple-page-server-only/$types').ActionData} */ +const actionData = { action: 'bar' }; +actionData.action; +// @ts-expect-error +actionData.foo; diff --git a/packages/kit/src/core/sync/write_types/test/simple-page-server-only/_expected/$types.d.ts b/packages/kit/src/core/sync/write_types/test/simple-page-server-only/_expected/$types.d.ts deleted file mode 100644 index 83443fcf45bc..000000000000 --- a/packages/kit/src/core/sync/write_types/test/simple-page-server-only/_expected/$types.d.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = {}; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type PageServerParentData = EnsureDefined; -type PageParentData = EnsureDefined; -type LayoutParams = RouteParams & {}; -type LayoutParentData = EnsureDefined<{}>; - -export type PageServerLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.ServerLoad; -export type PageServerLoadEvent = Parameters[0]; -export type ActionData = - | Expand> - | undefined; -export type PageServerData = Expand< - Kit.AwaitedProperties< - Awaited> - > ->; -export type PageData = Expand< - Omit & EnsureDefined ->; -export type Action = Kit.Action; -export type Actions = Kit.Actions; -export type LayoutServerData = null; -export type LayoutData = Expand; -export type RequestEvent = Kit.RequestEvent; diff --git a/packages/kit/src/core/sync/write_types/test/simple-page-server-only/sub/+page.server.js b/packages/kit/src/core/sync/write_types/test/simple-page-server-only/sub/+page.server.js new file mode 100644 index 000000000000..58b4c36ac541 --- /dev/null +++ b/packages/kit/src/core/sync/write_types/test/simple-page-server-only/sub/+page.server.js @@ -0,0 +1,16 @@ +/** @type {import('../.svelte-kit/types/src/core/sync/write_types/test/simple-page-server-only/sub/$types').PageServerLoad} */ +export function load() { + if (Math.random() > 0.5) { + return { + foo: 'bar' + }; + } +} + +/** @type {import('../.svelte-kit/types/src/core/sync/write_types/test/simple-page-server-only/sub/$types').PageData} */ +const data = /** @type {any} */ ({ + foo: 'bar' +}); // the any cast prevents TypeScript from narrowing this to foo being defined +data.foo; +// @ts-expect-error +data.foo.charAt(0); diff --git a/packages/kit/src/core/sync/write_types/test/simple-page-server-only/sub/+page.svelte b/packages/kit/src/core/sync/write_types/test/simple-page-server-only/sub/+page.svelte new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/+page.js b/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/+page.js index 3b51904671c5..900e9369bd13 100644 --- a/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/+page.js +++ b/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/+page.js @@ -3,3 +3,11 @@ export function load() { shared: 'shared' }; } + +/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/simple-page-shared-only/$types').PageData} */ +const data = { + shared: 'asd' +}; +data.shared; +// @ts-expect-error +data.bar; diff --git a/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/_expected/$types.d.ts b/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/_expected/$types.d.ts deleted file mode 100644 index bd9abf03bb14..000000000000 --- a/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/_expected/$types.d.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = {}; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type PageParentData = EnsureDefined; -type LayoutParams = RouteParams & {}; -type LayoutParentData = EnsureDefined<{}>; - -export type PageServerData = null; -export type PageLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.Load; -export type PageLoadEvent = Parameters[0]; -export type PageData = Expand< - Omit< - PageParentData, - keyof Kit.AwaitedProperties< - Awaited> - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited> - > - > ->; -export type LayoutServerData = null; -export type LayoutData = Expand; diff --git a/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/sub/+page.js b/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/sub/+page.js new file mode 100644 index 000000000000..b1d06b96d262 --- /dev/null +++ b/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/sub/+page.js @@ -0,0 +1,16 @@ +/** @type {import('../.svelte-kit/types/src/core/sync/write_types/test/simple-page-shared-only/sub/$types').PageLoad} */ +export function load() { + if (Math.random() > 0.5) { + return { + foo: 'bar' + }; + } +} + +/** @type {import('../.svelte-kit/types/src/core/sync/write_types/test/simple-page-shared-only/sub/$types').PageData} */ +const data = /** @type {any} */ ({ + foo: 'bar' +}); // the any cast prevents TypeScript from narrowing this to foo being defined +data.foo; +// @ts-expect-error +data.foo.charAt(0); diff --git a/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/sub/+page.svelte b/packages/kit/src/core/sync/write_types/test/simple-page-shared-only/sub/+page.svelte new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/+layout.js b/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/+layout.js index 23addb029828..f0ae674a8f07 100644 --- a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/+layout.js +++ b/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/+layout.js @@ -1 +1,5 @@ -export function load() {} +/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/$types').LayoutLoad} */ +export function load({ params }) { + params.rest; + params.slug; +} diff --git a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/$types.d.ts b/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/$types.d.ts deleted file mode 100644 index 84ca3b827252..000000000000 --- a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/$types.d.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = {}; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type LayoutParams = RouteParams & { rest?: string; slug?: string }; -type LayoutParentData = EnsureDefined<{}>; - -export type LayoutServerData = null; -export type LayoutLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.Load; -export type LayoutLoadEvent = Parameters[0]; -export type LayoutData = Expand< - Omit< - LayoutParentData, - keyof Kit.AwaitedProperties< - Awaited> - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited> - > - > ->; diff --git a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/nested/$types.d.ts b/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/nested/$types.d.ts deleted file mode 100644 index ceb75d063513..000000000000 --- a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/nested/$types.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = {}; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type LayoutParams = RouteParams & { rest?: string }; -type LayoutParentData = EnsureDefined; - -export type LayoutServerData = null; -export type LayoutLoad< - OutputData extends (Partial & Record) | void = - | (Partial & Record) - | void -> = Kit.Load; -export type LayoutLoadEvent = Parameters[0]; -export type LayoutData = Expand< - Omit< - LayoutParentData, - keyof Kit.AwaitedProperties< - Awaited> - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited> - > - > ->; diff --git a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/nested/[...rest]/$types.d.ts b/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/nested/[...rest]/$types.d.ts deleted file mode 100644 index 1f85afeb0254..000000000000 --- a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/nested/[...rest]/$types.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = { rest: string }; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type PageParentData = Omit< - EnsureDefined, - keyof import('../$types.js').LayoutData -> & - EnsureDefined; - -export type PageServerData = null; -export type PageLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.Load; -export type PageLoadEvent = Parameters[0]; -export type PageData = Expand< - Omit< - PageParentData, - keyof Kit.AwaitedProperties< - Awaited< - ReturnType - > - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited< - ReturnType - > - > - > ->; diff --git a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/nested/[slug]/$types.d.ts b/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/nested/[slug]/$types.d.ts deleted file mode 100644 index 1fed4661e16e..000000000000 --- a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/_expected/nested/[slug]/$types.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = { slug: string }; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type PageParentData = EnsureDefined; - -export type PageServerData = null; -export type PageData = Expand; diff --git a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/nested/+layout.js b/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/nested/+layout.js index 23addb029828..d41974fea45b 100644 --- a/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/nested/+layout.js +++ b/packages/kit/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/nested/+layout.js @@ -1 +1,6 @@ -export function load() {} +/** @type {import('../.svelte-kit/types/src/core/sync/write_types/test/slugs-layout-not-all-pages-have-load/nested/$types').LayoutLoad} */ +export function load({ params }) { + params.rest; + // @ts-expect-error + params.slug; +} diff --git a/packages/kit/src/core/sync/write_types/test/slugs/+layout.js b/packages/kit/src/core/sync/write_types/test/slugs/+layout.js index 23addb029828..8eea8cfcc18f 100644 --- a/packages/kit/src/core/sync/write_types/test/slugs/+layout.js +++ b/packages/kit/src/core/sync/write_types/test/slugs/+layout.js @@ -1 +1,14 @@ -export function load() {} +/** @type {import('./.svelte-kit/types/src/core/sync/write_types/test/slugs/$types').LayoutLoad} */ +export function load({ params }) { + params.optional; + params.rest; + params.slug; + // @ts-expect-error + params.foo; + // @ts-expect-error + params.optional.charAt(1); + // @ts-expect-error + params.rest.charAt(1); + // @ts-expect-error + params.slug.charAt(1); +} diff --git a/packages/kit/src/core/sync/write_types/test/slugs/[...rest]/+page.js b/packages/kit/src/core/sync/write_types/test/slugs/[...rest]/+page.js index 45fa74a24858..cdebe4d37303 100644 --- a/packages/kit/src/core/sync/write_types/test/slugs/[...rest]/+page.js +++ b/packages/kit/src/core/sync/write_types/test/slugs/[...rest]/+page.js @@ -1,3 +1,10 @@ -export function load() { +/** @type {import('../.svelte-kit/types/src/core/sync/write_types/test/slugs/[...rest]/$types').PageLoad} */ +export function load({ params }) { + params.rest.charAt(1); + // @ts-expect-error + params.optional; + // @ts-expect-error + params.slug; + return { rest: 'rest' }; } diff --git a/packages/kit/src/core/sync/write_types/test/slugs/[slug]/+page.js b/packages/kit/src/core/sync/write_types/test/slugs/[slug]/+page.js index 8e5a438b5c9f..9a82f5ab5782 100644 --- a/packages/kit/src/core/sync/write_types/test/slugs/[slug]/+page.js +++ b/packages/kit/src/core/sync/write_types/test/slugs/[slug]/+page.js @@ -1,3 +1,10 @@ -export function load() { +/** @type {import('../.svelte-kit/types/src/core/sync/write_types/test/slugs/[slug]/$types').PageLoad} */ +export function load({ params }) { + params.slug.charAt(1); + // @ts-expect-error + params.optional; + // @ts-expect-error + params.rest; + return { slug: 'slug' }; } diff --git a/packages/kit/src/core/sync/write_types/test/slugs/_expected/$types.d.ts b/packages/kit/src/core/sync/write_types/test/slugs/_expected/$types.d.ts deleted file mode 100644 index a3343d9cf1d9..000000000000 --- a/packages/kit/src/core/sync/write_types/test/slugs/_expected/$types.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = {}; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type LayoutParams = RouteParams & { rest?: string; slug?: string; optional?: string }; -type LayoutParentData = EnsureDefined<{}>; - -export type LayoutServerData = null; -export type LayoutLoad< - OutputData extends (Partial & Record) | void = - | (Partial & Record) - | void -> = Kit.Load; -export type LayoutLoadEvent = Parameters[0]; -export type LayoutData = Expand< - Omit< - LayoutParentData, - keyof Kit.AwaitedProperties< - Awaited> - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited> - > - > ->; diff --git a/packages/kit/src/core/sync/write_types/test/slugs/_expected/[...rest]/$types.d.ts b/packages/kit/src/core/sync/write_types/test/slugs/_expected/[...rest]/$types.d.ts deleted file mode 100644 index 3e9a9bf730bf..000000000000 --- a/packages/kit/src/core/sync/write_types/test/slugs/_expected/[...rest]/$types.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = { rest: string }; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type PageParentData = EnsureDefined; - -export type PageServerData = null; -export type PageLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.Load; -export type PageLoadEvent = Parameters[0]; -export type PageData = Expand< - Omit< - PageParentData, - keyof Kit.AwaitedProperties< - Awaited> - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited> - > - > ->; diff --git a/packages/kit/src/core/sync/write_types/test/slugs/_expected/[slug]/$types.d.ts b/packages/kit/src/core/sync/write_types/test/slugs/_expected/[slug]/$types.d.ts deleted file mode 100644 index ec1208796bf6..000000000000 --- a/packages/kit/src/core/sync/write_types/test/slugs/_expected/[slug]/$types.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = { slug: string }; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type PageParentData = EnsureDefined; - -export type PageServerData = null; -export type PageLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.Load; -export type PageLoadEvent = Parameters[0]; -export type PageData = Expand< - Omit< - PageParentData, - keyof Kit.AwaitedProperties< - Awaited> - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited> - > - > ->; diff --git a/packages/kit/src/core/sync/write_types/test/slugs/_expected/x/[[optional]]/$types.d.ts b/packages/kit/src/core/sync/write_types/test/slugs/_expected/x/[[optional]]/$types.d.ts deleted file mode 100644 index f25dbd0d3ab8..000000000000 --- a/packages/kit/src/core/sync/write_types/test/slugs/_expected/x/[[optional]]/$types.d.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -type RouteParams = { optional?: string }; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { - [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; -}[keyof T]; -type OutputDataShape = MaybeWithVoid< - Omit> & - Partial> & - Record ->; -type EnsureDefined = T extends null | undefined ? {} : T; -type PageParentData = EnsureDefined; - -export type PageServerData = null; -export type PageLoad< - OutputData extends OutputDataShape = OutputDataShape -> = Kit.Load; -export type PageLoadEvent = Parameters[0]; -export type PageData = Expand< - Omit< - PageParentData, - keyof Kit.AwaitedProperties< - Awaited< - ReturnType - > - > - > & - EnsureDefined< - Kit.AwaitedProperties< - Awaited< - ReturnType - > - > - > ->; diff --git a/packages/kit/src/core/sync/write_types/test/slugs/x/[[optional]]/+page.js b/packages/kit/src/core/sync/write_types/test/slugs/x/[[optional]]/+page.js index 41508314745e..4085ce7295cb 100644 --- a/packages/kit/src/core/sync/write_types/test/slugs/x/[[optional]]/+page.js +++ b/packages/kit/src/core/sync/write_types/test/slugs/x/[[optional]]/+page.js @@ -1,3 +1,21 @@ -export function load() { +/** @type {import('../../.svelte-kit/types/src/core/sync/write_types/test/slugs/x/[[optional]]/$types').PageLoad} */ +export async function load({ parent, params }) { + const p = await parent(); + /** @type {NonNullable} */ + const a = p; + // @ts-expect-error + p.foo; + // @ts-expect-error + a.foo; + + params.optional; + params.optional?.charAt(1); + // @ts-expect-error + params.optional.charAt(1); + // @ts-expect-error + params.slug; + // @ts-expect-error + params.rest; + return { optional: 'optional' }; } diff --git a/packages/kit/src/core/sync/write_types/test/tsconfig.json b/packages/kit/src/core/sync/write_types/test/tsconfig.json new file mode 100644 index 000000000000..14e7da72eb96 --- /dev/null +++ b/packages/kit/src/core/sync/write_types/test/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "noEmit": true, + "strict": true, + "target": "es2020", + "module": "es2022", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "baseUrl": ".", + "paths": { + "@sveltejs/kit": ["../../../../../types/index"] + } + }, + "include": ["./**/*.js"], + "exclude": ["./**/.svelte-kit/**"] +} diff --git a/packages/kit/tsconfig.json b/packages/kit/tsconfig.json index 75005513a5b9..1ad6e60fcfef 100644 --- a/packages/kit/tsconfig.json +++ b/packages/kit/tsconfig.json @@ -17,5 +17,5 @@ "noUnusedParameters": true }, "include": ["scripts/**/*", "src/**/*", "types/**/*"], - "exclude": ["./**/write_types/test/*/_expected/**"] + "exclude": ["./**/write_types/test/**"] }