-
-
Couldn't load subscription status.
- Fork 2.1k
Description
Describe the problem
I appreciate the thought & work that went into #11144 and #11165 but I think it's the wrong approach.
The confusion around return and throw arises from SvelteKit's original decision to stray from the common sense meanings of those words. I get there was a reason for this -- deriving action function return types, which can't be done if validation errors are thrown. But it led to a less than intuitive API...
return fail(400, {bah: 'humbug'})...ackthrow redirect(302, '/success')...ack (it's a success, you should be able to return it)throw redirect(302, '/login')...fair enoughthrow error(500)...fair enough
Hiding the throw in the redirect and error cases doesn't really fix the problem. It just kicks the can down the road.
- It replaces a well-understood keyword with a SvelteKit abstraction that does the same exact thing. The fact that it does the same thing has to be remembered or looked up.
- The
neverworks in an IDE. But you won't see the "unreachable code" lint if you're looking at something in a GitHub issue.
There's also a decent case to be made for...
const err = error(4xx, /** something complicated **/);
// throw it various places later...Describe the proposed solution
Consider rolling it back.
Alternatives considered
Ideally, the error handling API should be re-written to be simpler and more intuitive. Stick to to the easy-to-understand paradigm of throwing Error and returning success, like so...
// I think these already exist, but making up the names...
import type {InvalidFormError, Redirect, ExpectedError} from '@svelte/kit';
// always thrown...
throw new ExpectedError(403, {message: 'You cannot do that.'});
// validation errors always thrown...
throw new InvalidFormError(400, {...});
// redirects are thrown or returned...
return new Redirect(302, '/success'); // as the return value of an action
throw new Redirect(302, '/login'); // thrown from an auth check in an action or load functionGranted, this leaves out how to type Action return values, given that validation errors are thrown. I get that this typing is a feature, but I'm not convinced that it's super valuable in practice. The shape of form (and the enhance result) on the client usually needs to narrowed anyway, between success and failure states, and between actions if a route has more than one. The generated types become cumbersome. It's just simpler to cheat...
// auth/+page.svelte
import type { ActionData } from './$types.js';
export let form: ActionData;
$: actionData = form as any;
// passed to form components which have narrowed types...
// SignInForm.svelte
export let actionData: {data: SignInData, errors: {[k in keyof SignInData]?: string}};
// SignUpForm.svelte
export let actionData: {data: SignUpData, errors: {[k in keyof SignUpData]?: string}};I suppose it's a matter of opinion whether generating action types is worth increasing the eccentricity and surface of the framework API. I'm fine either way. It's easy enough to wrap away the eccentricities.
Importance
nice to have
Additional Information
No response