Skip to content

Commit 9e60c03

Browse files
committed
refactor(spawn-node): use assertion function instead of structural cast
TypeScript can't narrow a parent object from a typeof-check on one of its properties, which forced `spawnResult.process as { send: ... }` downstream of the existing runtime guard. Extract the guard into a small `assertHasSend` assertion function so the call site narrows cleanly and the structural cast is gone.
1 parent 65f0c72 commit 9e60c03

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

packages/cli/src/utils/spawn/spawn-node.mts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ import type {
3333
SpawnExtra,
3434
} from '@socketsecurity/lib/spawn'
3535

36+
/**
37+
* Narrows a spawned process to the shape required by
38+
* `sendBootstrapHandshake` (i.e. `.send` is a callable, not undefined).
39+
* The typeof-on-a-property guard can't flow to the parent object, so
40+
* we need an explicit assertion function.
41+
*/
42+
function assertHasSend<T extends { send?: unknown }>(
43+
proc: T,
44+
): asserts proc is T & { send: (message: unknown) => void } {
45+
if (typeof proc.send !== 'function') {
46+
throw new TypeError(
47+
'spawn-node: expected IPC channel on child process (send is undefined)',
48+
)
49+
}
50+
}
51+
3652
/**
3753
* Ensures stdio configuration includes IPC channel for process communication.
3854
* Converts various stdio formats to include 'ipc' as the fourth element.
@@ -117,13 +133,12 @@ export function spawnNode(
117133
extra,
118134
)
119135

120-
if (typeof spawnResult.process.send !== 'function') {
121-
throw new TypeError(
122-
'spawn-node: expected IPC channel on child process (send is undefined)',
123-
)
124-
}
136+
// `ensureIpcInStdio` above guarantees an IPC channel in stdio, so
137+
// `.send` should always be a function here. Narrow explicitly via an
138+
// assertion function so the call site doesn't need a structural cast.
139+
assertHasSend(spawnResult.process)
125140
sendBootstrapHandshake(
126-
spawnResult.process as { send: (message: unknown) => void },
141+
spawnResult.process,
127142
// Always send IPC handshake with bootstrap indicators + custom data.
128143
{
129144
subprocess: true,

0 commit comments

Comments
 (0)