Skip to content

fix(types): require send() payload when Reply type is specified#6432

Merged
mcollina merged 2 commits intofastify:mainfrom
tt-a1i:fix/send-required-param
Jan 3, 2026
Merged

fix(types): require send() payload when Reply type is specified#6432
mcollina merged 2 commits intofastify:mainfrom
tt-a1i:fix/send-required-param

Conversation

@tt-a1i
Copy link
Contributor

@tt-a1i tt-a1i commented Dec 31, 2025

Summary

When a Reply type is explicitly specified, the send() method now requires a payload argument instead of making it optional. This prevents silent bugs where developers forget to send the expected response type.

Closes #5534

Changes

  • Added SendArgs<ReplyType> helper type in types/type-provider.d.ts to determine payload requirement
  • Updated send() method signature in types/reply.d.ts to use spread parameters with SendArgs
  • Updated existing type tests to reflect new signature
  • Added new test cases verifying:
    • send() without arguments errors when Reply type is specified
    • send() without arguments is valid when Reply is void, undefined, or unspecified

Behavior

ReplyType send() payload
unknown (default) optional
void optional
undefined optional
Specific type (e.g. { test: boolean }) required

Note on undefined vs void: When using HTTP status code mappings like { 204: undefined }, the undefined gets converted to unknown via UndefinedToUnknown in type-provider.d.ts. This means send() is optional but send({}) is also allowed. Use void instead of undefined if you want stricter "no payload allowed" semantics.

Example

// Before: no error when forgetting to send payload
server.get<{ Reply: { test: boolean } }>('/', (req, reply) => {
  reply.send() // oops, forgot the payload - no TypeScript error
})

// After: TypeScript error
server.get<{ Reply: { test: boolean } }>('/', (req, reply) => {
  reply.send() // Error: Expected 1 argument, but got 0
  reply.send({ test: true }) // OK
})

AI Assistance Disclosure

I used Codex to review the changes, sanity-check the implementation against existing patterns, and help spot potential edge cases.

When a Reply type is explicitly provided, the `send()` method now
requires a payload argument instead of making it optional. This
improves type safety by catching cases where developers forget to
send a response.

The behavior is:
- When ReplyType is `unknown` (default): payload is optional
- When ReplyType is `undefined` or `void`: payload is optional
- Otherwise: payload is required

Closes fastify#5534
@github-actions github-actions bot added the typescript TypeScript related label Dec 31, 2025
@tt-a1i tt-a1i force-pushed the fix/send-required-param branch 2 times, most recently from 901a316 to a4ec9db Compare December 31, 2025 15:27
@tt-a1i tt-a1i force-pushed the fix/send-required-param branch from a4ec9db to 189b59a Compare December 31, 2025 15:29
@tt-a1i tt-a1i marked this pull request as ready for review December 31, 2025 15:33
@Eomm Eomm requested a review from a team January 2, 2026 16:41
Copy link
Member

@gurgunday gurgunday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this lgtm

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcollina mcollina merged commit c02c5f5 into fastify:main Jan 3, 2026
31 checks passed
@smellai
Copy link

smellai commented Jan 29, 2026

Hi, this includes a breaking change but didn't trigger a major release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

typescript TypeScript related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Suggestion for Fastify 5: Required param to .send

5 participants