Skip to content

Commit a831292

Browse files
committed
fix(core): add | undefined to Transport optional callback types for exactOptionalPropertyTypes compatibility
Resolves TS2420 errors when users implement the Transport interface in projects with `exactOptionalPropertyTypes: true` enabled. Optional callback properties (onclose, onerror, onmessage, setProtocolVersion, setSupportedProtocolVersions) now include explicit `| undefined` in their types, satisfying the stricter assignability rules. Fixes #1314
1 parent 108f2f3 commit a831292

3 files changed

Lines changed: 48 additions & 5 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@modelcontextprotocol/core': patch
3+
---
4+
5+
Fix TS2420 error when implementing Transport with exactOptionalPropertyTypes enabled
6+
7+
Optional callback properties on the Transport interface (`onclose`, `onerror`, `onmessage`, `setProtocolVersion`, `setSupportedProtocolVersions`) now explicitly include `| undefined` in their type signature. This makes the interface compatible with TypeScript's `exactOptionalPropertyTypes` compiler option, which was previously causing TS2420 "Class incorrectly implements interface" errors for users with that flag enabled.

packages/core/src/shared/transport.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,14 @@ export interface Transport {
9898
*
9999
* This should be invoked when {@linkcode Transport.close | close()} is called as well.
100100
*/
101-
onclose?: () => void;
101+
onclose?: (() => void) | undefined;
102102

103103
/**
104104
* Callback for when an error occurs.
105105
*
106106
* Note that errors are not necessarily fatal; they are used for reporting any kind of exceptional condition out of band.
107107
*/
108-
onerror?: (error: Error) => void;
108+
onerror?: ((error: Error) => void) | undefined;
109109

110110
/**
111111
* Callback for when a message (request or response) is received over the connection.
@@ -114,7 +114,7 @@ export interface Transport {
114114
*
115115
* The {@linkcode MessageExtraInfo.requestInfo | requestInfo} can be used to get the original request information (headers, etc.)
116116
*/
117-
onmessage?: <T extends JSONRPCMessage>(message: T, extra?: MessageExtraInfo) => void;
117+
onmessage?: (<T extends JSONRPCMessage>(message: T, extra?: MessageExtraInfo) => void) | undefined;
118118

119119
/**
120120
* The session ID generated for this connection.
@@ -124,11 +124,11 @@ export interface Transport {
124124
/**
125125
* Sets the protocol version used for the connection (called when the initialize response is received).
126126
*/
127-
setProtocolVersion?: (version: string) => void;
127+
setProtocolVersion?: ((version: string) => void) | undefined;
128128

129129
/**
130130
* Sets the supported protocol versions for header validation (called during connect).
131131
* This allows the server to pass its supported versions to the transport.
132132
*/
133-
setSupportedProtocolVersions?: (versions: string[]) => void;
133+
setSupportedProtocolVersions?: ((versions: string[]) => void) | undefined;
134134
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Compile-time type checks for the Transport interface.
3+
*
4+
* Verifies that a class declaring optional callback properties as `T | undefined`
5+
* (the pattern required by `exactOptionalPropertyTypes: true`) is assignable to
6+
* Transport without TS2420 errors.
7+
*
8+
* See: https://github.com/modelcontextprotocol/typescript-sdk/issues/1314
9+
*/
10+
import { test } from 'vitest';
11+
12+
import type { Transport } from '../../src/shared/transport.js';
13+
import type { JSONRPCMessage, MessageExtraInfo } from '../../src/types/types.js';
14+
15+
// A concrete class that uses the explicit `| undefined` union form for optional callbacks.
16+
// With the old Transport interface (no `| undefined` on callbacks), this class would produce
17+
// TS2420 under `exactOptionalPropertyTypes: true`.
18+
class ExplicitUndefinedTransport implements Transport {
19+
sessionId?: string | undefined;
20+
onclose?: (() => void) | undefined;
21+
onerror?: ((error: Error) => void) | undefined;
22+
onmessage?: (<T extends JSONRPCMessage>(message: T, extra?: MessageExtraInfo) => void) | undefined;
23+
setProtocolVersion?: ((version: string) => void) | undefined;
24+
setSupportedProtocolVersions?: ((versions: string[]) => void) | undefined;
25+
26+
async start(): Promise<void> {}
27+
async close(): Promise<void> {}
28+
async send(_message: JSONRPCMessage): Promise<void> {}
29+
}
30+
31+
test('Transport allows explicit | undefined on optional callback properties', () => {
32+
const transport: Transport = new ExplicitUndefinedTransport();
33+
// The mere fact this file compiles is the assertion.
34+
// We also verify runtime assignability here.
35+
expect(transport).toBeDefined();
36+
});

0 commit comments

Comments
 (0)