Skip to content

Conversation

@bjorndown
Copy link

I would like to be able to write handlers with early returns like this:

import { NextApiHandler } from 'next'

const handler: NextApiHandler = (req, res) => {
  const value = getStuff()
  if (value === 'branch') {
    return res.json({}) 
  }
  res.status(400)
}

but NextApiHandler's current return type is void | Promise<void>, which causes compilation to fail with

Error:(11, 3) TS2322: Type '(req: NextApiRequest, res: NextApiResponse<any>) => Promise<NextApiResponse<any> | undefined>' is not assignable to type 'NextApiHandler<any>'.
  Type 'Promise<NextApiResponse<any> | undefined>' is not assignable to type 'void | Promise<void>'.
    Type 'Promise<NextApiResponse<any> | undefined>' is not assignable to type 'Promise<void>'.
      Type 'NextApiResponse<any> | undefined' is not assignable to type 'void'.
        Type 'NextApiResponse<any>' is not assignable to type 'void'.

to avoid that the above snippet needs to be written as

  if (value === 'branch') {
    res.json({}) 
    return
  }

which looks odd to me. Changing the return type of NextApiHandler to unknown | Promise<unknown> would allow for shorter early returns and still communicates to users that nothing is expected to be returned from a handler.

Augmenting the type like this, makes the first snippet work:

import { NextApiRequest, NextApiResponse } from 'next'

declare module 'next' {
  export declare type NextApiHandler<T = any> = (
    req: NextApiRequest,
    res: NextApiResponse<T>
  ) => unknown | Promise<unknown>
}

Bug

  • Related issues linked using fixes #number
  • Integration tests added
  • Errors have helpful link attached, see contributing.md

Feature

  • Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
  • Related issues linked using fixes #number
  • Integration tests added
  • Documentation added
  • Telemetry added. In case of a feature if it's used or not.
  • Errors have helpful link attached, see contributing.md

Documentation / Examples

  • Make sure the linting passes by running yarn lint

@ijjk
Copy link
Member

ijjk commented Mar 12, 2022

Stats from current PR

Default Build (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary bjorm/next.js patch-1 Change
buildDuration 17.4s 17.2s -239ms
buildDurationCached 7.2s 7s -208ms
nodeModulesSize 485 MB 485 MB ⚠️ +6 B
Page Load Tests Overall increase ✓
vercel/next.js canary bjorm/next.js patch-1 Change
/ failed reqs 0 0
/ total time (seconds) 3.679 3.503 -0.18
/ avg req/sec 679.5 713.77 +34.27
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.662 1.514 -0.15
/error-in-render avg req/sec 1503.96 1650.96 +147
Client Bundles (main, webpack)
vercel/next.js canary bjorm/next.js patch-1 Change
925.HASH.js gzip 179 B 179 B
framework-HASH.js gzip 42 kB 42 kB
main-HASH.js gzip 28.3 kB 28.3 kB
webpack-HASH.js gzip 1.44 kB 1.44 kB
Overall change 72 kB 72 kB
Legacy Client Bundles (polyfills)
vercel/next.js canary bjorm/next.js patch-1 Change
polyfills-HASH.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages
vercel/next.js canary bjorm/next.js patch-1 Change
_app-HASH.js gzip 1.36 kB 1.36 kB
_error-HASH.js gzip 192 B 192 B
amp-HASH.js gzip 309 B 309 B
css-HASH.js gzip 327 B 327 B
dynamic-HASH.js gzip 3.04 kB 3.04 kB
head-HASH.js gzip 351 B 351 B
hooks-HASH.js gzip 920 B 920 B
image-HASH.js gzip 5.74 kB 5.74 kB
index-HASH.js gzip 263 B 263 B
link-HASH.js gzip 2.36 kB 2.36 kB
routerDirect..HASH.js gzip 320 B 320 B
script-HASH.js gzip 392 B 392 B
withRouter-HASH.js gzip 319 B 319 B
85e02e95b279..7e3.css gzip 107 B 107 B
Overall change 16 kB 16 kB
Client Build Manifests
vercel/next.js canary bjorm/next.js patch-1 Change
_buildManifest.js gzip 461 B 461 B
Overall change 461 B 461 B
Rendered Page Sizes
vercel/next.js canary bjorm/next.js patch-1 Change
index.html gzip 530 B 530 B
link.html gzip 544 B 544 B
withRouter.html gzip 524 B 524 B
Overall change 1.6 kB 1.6 kB

Default Build with SWC (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary bjorm/next.js patch-1 Change
buildDuration 20.2s 20s -209ms
buildDurationCached 6.6s 7.2s ⚠️ +572ms
nodeModulesSize 485 MB 485 MB ⚠️ +6 B
Page Load Tests Overall increase ✓
vercel/next.js canary bjorm/next.js patch-1 Change
/ failed reqs 0 0
/ total time (seconds) 3.69 3.603 -0.09
/ avg req/sec 677.54 693.87 +16.33
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.613 1.541 -0.07
/error-in-render avg req/sec 1550.2 1622.69 +72.49
Client Bundles (main, webpack)
vercel/next.js canary bjorm/next.js patch-1 Change
925.HASH.js gzip 178 B 178 B
framework-HASH.js gzip 42.3 kB 42.3 kB
main-HASH.js gzip 28.7 kB 28.7 kB
webpack-HASH.js gzip 1.45 kB 1.45 kB
Overall change 72.6 kB 72.6 kB
Legacy Client Bundles (polyfills)
vercel/next.js canary bjorm/next.js patch-1 Change
polyfills-HASH.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages
vercel/next.js canary bjorm/next.js patch-1 Change
_app-HASH.js gzip 1.35 kB 1.35 kB
_error-HASH.js gzip 179 B 179 B
amp-HASH.js gzip 313 B 313 B
css-HASH.js gzip 325 B 325 B
dynamic-HASH.js gzip 3.02 kB 3.02 kB
head-HASH.js gzip 351 B 351 B
hooks-HASH.js gzip 921 B 921 B
image-HASH.js gzip 5.78 kB 5.78 kB
index-HASH.js gzip 261 B 261 B
link-HASH.js gzip 2.44 kB 2.44 kB
routerDirect..HASH.js gzip 322 B 322 B
script-HASH.js gzip 393 B 393 B
withRouter-HASH.js gzip 317 B 317 B
85e02e95b279..7e3.css gzip 107 B 107 B
Overall change 16.1 kB 16.1 kB
Client Build Manifests
vercel/next.js canary bjorm/next.js patch-1 Change
_buildManifest.js gzip 457 B 457 B
Overall change 457 B 457 B
Rendered Page Sizes
vercel/next.js canary bjorm/next.js patch-1 Change
index.html gzip 532 B 532 B
link.html gzip 545 B 545 B
withRouter.html gzip 526 B 526 B
Overall change 1.6 kB 1.6 kB
Commit: afab31c

bjorndown and others added 2 commits March 28, 2022 08:51
I would like to be able to write handlers like this

```typescript
import { NextApiHandler } from 'next'

const handler: NextApiHandler = (req, res) => {
  const value = getStuff()
  if (value === 'branch') {
    return res.json({}) // return early
  }
  res.status(400)
}
```

but `NextApiHandler`'s current return type is `void | Promise<void>`, which causes compilation to fail with

```
Error:(11, 3) TS2322: Type '(req: NextApiRequest, res: NextApiResponse<any>) => Promise<NextApiResponse<any> | undefined>' is not assignable to type 'NextApiHandler<any>'.
  Type 'Promise<NextApiResponse<any> | undefined>' is not assignable to type 'void | Promise<void>'.
    Type 'Promise<NextApiResponse<any> | undefined>' is not assignable to type 'Promise<void>'.
      Type 'NextApiResponse<any> | undefined' is not assignable to type 'void'.
        Type 'NextApiResponse<any>' is not assignable to type 'void'.
```
to avoid that the above snippet needs to be written as

```typescript
  if (value === 'branch') {
    res.json({}) 
    return
  }
```
which looks odd to me. Changing the return type of `NextApiHandler` to `unknown | Promise<unknown>` would allow for shorter early returns and still communicates to users that nothing is expected to be returned from a handler.

Augmenting the type like this makes the first snippet work:
```
import { NextApiRequest, NextApiResponse } from 'next'

declare module 'next' {
  export declare type NextApiHandler<T = any> = (
    req: NextApiRequest,
    res: NextApiResponse<T>
  ) => unknown | Promise<unknown>
}
```
@kodiakhq kodiakhq bot merged commit f73e7d5 into vercel:canary Apr 16, 2022
SukkaW pushed a commit to SukkaW/next.js that referenced this pull request Apr 18, 2022
I would like to be able to write handlers with early returns like this:

```typescript
import { NextApiHandler } from 'next'

const handler: NextApiHandler = (req, res) => {
  const value = getStuff()
  if (value === 'branch') {
    return res.json({}) 
  }
  res.status(400)
}
```

but `NextApiHandler`'s current return type is `void | Promise<void>`, which causes compilation to fail with

```
Error:(11, 3) TS2322: Type '(req: NextApiRequest, res: NextApiResponse<any>) => Promise<NextApiResponse<any> | undefined>' is not assignable to type 'NextApiHandler<any>'.
  Type 'Promise<NextApiResponse<any> | undefined>' is not assignable to type 'void | Promise<void>'.
    Type 'Promise<NextApiResponse<any> | undefined>' is not assignable to type 'Promise<void>'.
      Type 'NextApiResponse<any> | undefined' is not assignable to type 'void'.
        Type 'NextApiResponse<any>' is not assignable to type 'void'.
```
to avoid that the above snippet needs to be written as

```typescript
  if (value === 'branch') {
    res.json({}) 
    return
  }
```
which looks odd to me. Changing the return type of `NextApiHandler` to `unknown | Promise<unknown>` would allow for shorter early returns and still communicates to users that nothing is expected to be returned from a handler.

Augmenting the type like this, makes the first snippet work:
```typescript
import { NextApiRequest, NextApiResponse } from 'next'

declare module 'next' {
  export declare type NextApiHandler<T = any> = (
    req: NextApiRequest,
    res: NextApiResponse<T>
  ) => unknown | Promise<unknown>
}
```



## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `yarn lint`
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 16, 2022
@bjorndown bjorndown deleted the patch-1 branch November 5, 2022 13:24
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants