Skip to content

Commit d28d372

Browse files
dummdidummteemingc
andauthored
fix: allow optional types for remote query/command/prerender functions (#15293)
We're using the `arg: undefined extends Input ? Input | void : Input` method and not the `...args: undefined extends Input ? [arg?: Input] : [arg: Input]` method because the former does work in more cases (the latter throws a type error in our own code around generics), even though the TS team likely wants us to use the latter (but that pattern is in so many code bases now that this behavior around `void` will never change). One drawback (of either method) is that without strict mode all commands/queries/prerenders have optional args now, because `undefined extends X` is always `true` in non-strict mode. But since noone who uses type checking nowadays should use non-strict mode anyway, it's fine. fixes #14500 --- ### Please don't delete this checklist! Before submitting the PR, please make sure you do the following: - [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs - [x] This message body should clearly illustrate what problems it solves. - [x] Ideally, include a test that fails without this PR but passes with it. ### Tests - [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check` ### Changesets - [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`. Co-authored-by: Tee Ming <chewteeming01@gmail.com>
1 parent 244838c commit d28d372

File tree

4 files changed

+65
-6
lines changed

4 files changed

+65
-6
lines changed

.changeset/violet-things-wear.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
fix: allow optional types for remote query/command/prerender functions

packages/kit/src/exports/public.d.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2110,7 +2110,7 @@ export type RemoteForm<Input extends RemoteFormInput | void, Output> = {
21102110
* The return value of a remote `command` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#command) for full documentation.
21112111
*/
21122112
export type RemoteCommand<Input, Output> = {
2113-
(arg: Input): Promise<Awaited<Output>> & {
2113+
(arg: undefined extends Input ? Input | void : Input): Promise<Awaited<Output>> & {
21142114
updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<Awaited<Output>>;
21152115
};
21162116
/** The number of pending command executions */
@@ -2180,11 +2180,15 @@ export interface RemoteQueryOverride {
21802180
/**
21812181
* The return value of a remote `prerender` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#prerender) for full documentation.
21822182
*/
2183-
export type RemotePrerenderFunction<Input, Output> = (arg: Input) => RemoteResource<Output>;
2183+
export type RemotePrerenderFunction<Input, Output> = (
2184+
arg: undefined extends Input ? Input | void : Input
2185+
) => RemoteResource<Output>;
21842186

21852187
/**
21862188
* The return value of a remote `query` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#query) for full documentation.
21872189
*/
2188-
export type RemoteQueryFunction<Input, Output> = (arg: Input) => RemoteQuery<Output>;
2190+
export type RemoteQueryFunction<Input, Output> = (
2191+
arg: undefined extends Input ? Input | void : Input
2192+
) => RemoteQuery<Output>;
21892193

21902194
export * from './index.js';

packages/kit/test/types/remote.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010

1111
const schema: StandardSchemaV1<string> = null as any;
1212
const schema2: StandardSchemaV1<string, number> = null as any;
13+
const schema3: StandardSchemaV1<string | undefined, number> = null as any;
1314

1415
function query_tests() {
1516
const no_args: RemoteQueryFunction<void, string> = query(() => 'Hello world');
@@ -40,6 +41,21 @@ function query_tests() {
4041
}
4142
void query_without_args();
4243

44+
async function query_with_optional_arg() {
45+
const q = query(schema3, () => 'Hello world');
46+
void q();
47+
void q('hi');
48+
// @ts-expect-error
49+
void q(1);
50+
51+
const q2 = query('unchecked', (a?: string) => a);
52+
void q2();
53+
void q2('hi');
54+
// @ts-expect-error
55+
void q2(1);
56+
}
57+
void query_with_optional_arg();
58+
4359
async function query_unsafe() {
4460
const q = query('unchecked', (a: number) => a);
4561
const result: number = await q(1);
@@ -106,6 +122,21 @@ function prerender_tests() {
106122
}
107123
void prerender_unsafe();
108124

125+
async function prerender_with_optional_arg() {
126+
const q = prerender(schema3, () => 'Hello world');
127+
void q();
128+
void q('hi');
129+
// @ts-expect-error
130+
void q(1);
131+
132+
const q2 = prerender('unchecked', (a?: string) => a);
133+
void q2();
134+
void q2('hi');
135+
// @ts-expect-error
136+
void q2(1);
137+
}
138+
void prerender_with_optional_arg();
139+
109140
async function prerender_schema() {
110141
const q = prerender(schema, (a) => a);
111142
const result: string = await q('1');
@@ -141,6 +172,21 @@ function command_tests() {
141172
}
142173
void command_without_args();
143174

175+
async function command_with_optional_arg() {
176+
const q = command(schema3, () => 'Hello world');
177+
void q();
178+
void q('hi');
179+
// @ts-expect-error
180+
void q(1);
181+
182+
const q2 = command('unchecked', (a?: string) => a);
183+
void q2();
184+
void q2('hi');
185+
// @ts-expect-error
186+
void q2(1);
187+
}
188+
void command_with_optional_arg();
189+
144190
async function command_unsafe() {
145191
const cmd = command('unchecked', (a: string) => a);
146192
const result: string = await cmd('test');

packages/kit/types/index.d.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,7 +2085,7 @@ declare module '@sveltejs/kit' {
20852085
* The return value of a remote `command` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#command) for full documentation.
20862086
*/
20872087
export type RemoteCommand<Input, Output> = {
2088-
(arg: Input): Promise<Awaited<Output>> & {
2088+
(arg: undefined extends Input ? Input | void : Input): Promise<Awaited<Output>> & {
20892089
updates(...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Promise<Awaited<Output>>;
20902090
};
20912091
/** The number of pending command executions */
@@ -2155,12 +2155,16 @@ declare module '@sveltejs/kit' {
21552155
/**
21562156
* The return value of a remote `prerender` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#prerender) for full documentation.
21572157
*/
2158-
export type RemotePrerenderFunction<Input, Output> = (arg: Input) => RemoteResource<Output>;
2158+
export type RemotePrerenderFunction<Input, Output> = (
2159+
arg: undefined extends Input ? Input | void : Input
2160+
) => RemoteResource<Output>;
21592161

21602162
/**
21612163
* The return value of a remote `query` function. See [Remote functions](https://svelte.dev/docs/kit/remote-functions#query) for full documentation.
21622164
*/
2163-
export type RemoteQueryFunction<Input, Output> = (arg: Input) => RemoteQuery<Output>;
2165+
export type RemoteQueryFunction<Input, Output> = (
2166+
arg: undefined extends Input ? Input | void : Input
2167+
) => RemoteQuery<Output>;
21642168
interface AdapterEntry {
21652169
/**
21662170
* A string that uniquely identifies an HTTP service (e.g. serverless function) and is used for deduplication.

0 commit comments

Comments
 (0)