Skip to content

Commit

Permalink
fix: notFound() and redirect() should return never
Browse files Browse the repository at this point in the history
The reason being is you can't actually give JSON to these types, and the page goes away when these happen, so it's logically the same as throwing

It also cleans up unions; before, an empty object type could show up in the props type, but `never` "dissolves" itself in unions
  • Loading branch information
itsMapleLeaf committed Sep 22, 2021
1 parent 0029874 commit 05b2126
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 31 deletions.
41 changes: 24 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"test:e2e": "cross-env type=e2e jest --runInBand ./pages",
"version": "npm run build",
"postversion": "cp -r docs README.md package.json lib",
"release": "np --contents=./lib --message='release: cut the `%s` release' --no-yarn --no-2fa"
"release": "np --contents=./lib --message='release: cut the `%s` release' --no-yarn --no-2fa",
"typecheck": "tsc --noEmit"
},
"main": "./index.js",
"source": "./src/index.ts",
Expand Down
2 changes: 1 addition & 1 deletion pages/pending-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const getServerSideProps = handle({
await setTimeout(1000);
toggle = !toggle;
console.log('POST', toggle);
return redirect<never>(context.req.url!, 303);
return redirect(context.req.url!, 303);
},
});

Expand Down
35 changes: 23 additions & 12 deletions src/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ export type ResponseInit = Pick<
>;
export type ResponseType = 'not-found' | 'redirect' | 'json';

function createResponse<T>(
body: { [key: string]: any },
init: ResponseInit,
type: ResponseType,
): TypedResponse<T> {
function createResponse<T>({
body = {} as T,
init,
type,
}: {
body?: T;
init: ResponseInit;
type: ResponseType;
}): TypedResponse<T> {
const response = new Response(JSON.stringify(body), init) as TypedResponse<T>;
response.headers.set('x-next-runtime-type', type);
return response;
Expand All @@ -27,9 +31,9 @@ function createResponse<T>(
/**
* Send the user a 404
*/
export function notFound<TProps>(
export function notFound(
init: number | ResponseInit = 404,
): TypedResponse<TProps> {
): TypedResponse<never> {
let responseInit: ResponseInit;

if (typeof init === 'number') {
Expand All @@ -38,16 +42,16 @@ export function notFound<TProps>(
responseInit = { status: 404, ...init };
}

return createResponse({}, responseInit, 'not-found');
return createResponse<never>({ init: responseInit, type: 'not-found' });
}

/**
* Redirect the user to another page. Defaults to temporary redirect.
*/
export function redirect<TProps>(
export function redirect(
destination: string,
init: number | ResponseInit | { permanent: boolean } = 302,
): RuntimeResponse<TProps> {
): RuntimeResponse<never> {
let responseInit: ResponseInit;

if (typeof init === 'number') {
Expand All @@ -61,7 +65,10 @@ export function redirect<TProps>(
const headers = new Headers(responseInit.headers);
headers.set('Location', destination);

return createResponse({}, { ...responseInit, headers }, 'redirect');
return createResponse<never>({
init: { ...responseInit, headers },
type: 'redirect',
});
}

/**
Expand All @@ -84,5 +91,9 @@ export function json<TProps>(
headers.set('Content-Type', 'application/json; charset=utf-8');
}

return createResponse(props, { ...responseInit, headers }, 'json');
return createResponse({
body: props,
init: { ...responseInit, headers },
type: 'json',
});
}

0 comments on commit 05b2126

Please sign in to comment.