Skip to content

Commit 3ce1ffe

Browse files
authored
🤖 Merge PR DefinitelyTyped#74773 [node] Fix Web Streams chunk parameter optionality by @ikeyan
1 parent dc3359e commit 3ce1ffe

File tree

12 files changed

+434
-18
lines changed

12 files changed

+434
-18
lines changed

‎types/node/node-tests.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import "./node-tests/repl";
3030
import "./node-tests/sea";
3131
import "./node-tests/sqlite";
3232
import "./node-tests/stream";
33+
import "./node-tests/stream-web";
3334
import "./node-tests/string_decoder";
3435
import "./node-tests/test";
3536
import "./node-tests/timers_promises";
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import assert from "node:assert";
2+
import { ReadableStream, TransformStream, WritableStream } from "node:stream/web";
3+
import type { QueuingStrategySize } from "node:stream/web";
4+
5+
async function readResultHasRequiredValueProperty() {
6+
const stream = ReadableStream.from(["test"]);
7+
const reader = stream.getReader();
8+
{
9+
const result = await reader.read();
10+
assert(!result.done, "Expected a non-done result");
11+
// $ExpectType string
12+
result.value;
13+
assert.strictEqual(result.value, "test");
14+
}
15+
{
16+
const result = await reader.read();
17+
assert(result.done, "Expected a done result");
18+
// $ExpectType string | undefined
19+
result.value;
20+
21+
assert.strictEqual(Object.prototype.hasOwnProperty.call(result, "value"), true);
22+
assert.strictEqual(result.value, undefined);
23+
}
24+
}
25+
26+
async function readableStreamControllerTreatsExplicitUndefinedAsAChunk() {
27+
const stream = new ReadableStream<string | undefined>({
28+
start(controller) {
29+
// @ts-expect-error `chunk` is required; pass `undefined` explicitly when it is part of the chunk type.
30+
controller.enqueue();
31+
controller.enqueue(undefined);
32+
controller.close();
33+
},
34+
});
35+
const values: (string | undefined)[] = [];
36+
for await (const chunk of stream) {
37+
values.push(chunk);
38+
}
39+
// enqueue() and enqueue(undefined) should have the same effect
40+
assert.deepStrictEqual(values, [undefined, undefined]);
41+
}
42+
43+
async function transformStreamControllerTreatsExplicitUndefinedAsAChunk() {
44+
const stream = new TransformStream<string, string | undefined>({
45+
transform(chunk, controller) {
46+
assert.strictEqual(chunk, "input");
47+
48+
// @ts-expect-error `chunk` is required; pass `undefined` explicitly when it is part of the chunk type.
49+
controller.enqueue();
50+
controller.enqueue(undefined);
51+
},
52+
});
53+
const values: (string | undefined)[] = [];
54+
for await (const chunk of ReadableStream.from(["input"]).pipeThrough(stream)) {
55+
values.push(chunk);
56+
}
57+
// enqueue() and enqueue(undefined) should have the same effect
58+
assert.deepStrictEqual(values, [undefined, undefined]);
59+
}
60+
61+
async function writableStreamWriterTreatsExplicitUndefinedAsAChunk() {
62+
const writtenChunks: (string | undefined)[] = [];
63+
64+
const stream = new WritableStream<string | undefined>({
65+
write(chunk) {
66+
writtenChunks.push(chunk);
67+
},
68+
});
69+
const writer = stream.getWriter();
70+
// @ts-expect-error `chunk` is required; pass `undefined` explicitly when it is part of the chunk type.
71+
await writer.write();
72+
await writer.write(undefined);
73+
await writer.close();
74+
75+
assert.deepStrictEqual(writtenChunks, [undefined, undefined]);
76+
}
77+
78+
async function queuingStrategySizeReceivesTheChunk() {
79+
const sizeChunks: string[] = [];
80+
81+
const size: QueuingStrategySize<string> = (chunk) => {
82+
// $ExpectType string
83+
chunk;
84+
sizeChunks.push(chunk);
85+
return chunk.length;
86+
};
87+
88+
const stream = new ReadableStream<string>(
89+
{
90+
start(controller) {
91+
controller.enqueue("size");
92+
controller.close();
93+
},
94+
},
95+
{
96+
highWaterMark: 10,
97+
size,
98+
},
99+
);
100+
const result = await stream.getReader().read();
101+
assert.deepStrictEqual(result, { done: false, value: "size" });
102+
assert.deepStrictEqual(sizeChunks, ["size"]);
103+
}

‎types/node/stream/web.d.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ declare module "node:stream/web" {
206206
interface ReadableStreamDefaultController<R = any> {
207207
readonly desiredSize: number | null;
208208
close(): void;
209-
enqueue(chunk?: R): void;
209+
enqueue(chunk: R): void;
210210
error(e?: any): void;
211211
}
212212
var ReadableStreamDefaultController: {
@@ -251,7 +251,7 @@ declare module "node:stream/web" {
251251
};
252252
interface TransformStreamDefaultController<O = any> {
253253
readonly desiredSize: number | null;
254-
enqueue(chunk?: O): void;
254+
enqueue(chunk: O): void;
255255
error(reason?: any): void;
256256
terminate(): void;
257257
}
@@ -284,7 +284,7 @@ declare module "node:stream/web" {
284284
abort(reason?: any): Promise<void>;
285285
close(): Promise<void>;
286286
releaseLock(): void;
287-
write(chunk?: W): Promise<void>;
287+
write(chunk: W): Promise<void>;
288288
}
289289
var WritableStreamDefaultWriter: {
290290
prototype: WritableStreamDefaultWriter;

‎types/node/v20/node-tests.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import "./test/readline";
2828
import "./test/repl";
2929
import "./test/sea";
3030
import "./test/stream";
31+
import "./test/stream-web";
3132
import "./test/string_decoder";
3233
import "./test/test";
3334
import "./test/timers_promises";

‎types/node/v20/stream/web.d.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ declare module "stream/web" {
109109
}
110110
interface ReadableStreamReadDoneResult<T> {
111111
done: true;
112-
value?: T;
112+
value: T | undefined;
113113
}
114114
type ReadableStreamReadResult<T> = ReadableStreamReadValueResult<T> | ReadableStreamReadDoneResult<T>;
115115
interface ReadableByteStreamControllerCallback {
@@ -251,7 +251,7 @@ declare module "stream/web" {
251251
interface ReadableStreamDefaultController<R = any> {
252252
readonly desiredSize: number | null;
253253
close(): void;
254-
enqueue(chunk?: R): void;
254+
enqueue(chunk: R): void;
255255
error(e?: any): void;
256256
}
257257
const ReadableStreamDefaultController: {
@@ -279,7 +279,7 @@ declare module "stream/web" {
279279
};
280280
interface TransformStreamDefaultController<O = any> {
281281
readonly desiredSize: number | null;
282-
enqueue(chunk?: O): void;
282+
enqueue(chunk: O): void;
283283
error(reason?: any): void;
284284
terminate(): void;
285285
}
@@ -315,7 +315,7 @@ declare module "stream/web" {
315315
abort(reason?: any): Promise<void>;
316316
close(): Promise<void>;
317317
releaseLock(): void;
318-
write(chunk?: W): Promise<void>;
318+
write(chunk: W): Promise<void>;
319319
}
320320
const WritableStreamDefaultWriter: {
321321
prototype: WritableStreamDefaultWriter;
@@ -339,7 +339,7 @@ declare module "stream/web" {
339339
size?: QueuingStrategySize<T>;
340340
}
341341
interface QueuingStrategySize<T = any> {
342-
(chunk?: T): number;
342+
(chunk: T): number;
343343
}
344344
interface QueuingStrategyInit {
345345
/**
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import assert from "node:assert";
2+
import { ReadableStream, TransformStream, WritableStream } from "node:stream/web";
3+
import type { QueuingStrategySize } from "node:stream/web";
4+
5+
async function readResultHasRequiredValueProperty() {
6+
const stream = ReadableStream.from(["test"]);
7+
const reader = stream.getReader();
8+
{
9+
const result = await reader.read();
10+
assert(!result.done, "Expected a non-done result");
11+
// $ExpectType string
12+
result.value;
13+
assert.strictEqual(result.value, "test");
14+
}
15+
{
16+
const result = await reader.read();
17+
assert(result.done, "Expected a done result");
18+
// $ExpectType string | undefined
19+
result.value;
20+
21+
assert.strictEqual(Object.prototype.hasOwnProperty.call(result, "value"), true);
22+
assert.strictEqual(result.value, undefined);
23+
}
24+
}
25+
26+
async function readableStreamControllerTreatsExplicitUndefinedAsAChunk() {
27+
const stream = new ReadableStream<string | undefined>({
28+
start(controller) {
29+
// @ts-expect-error `chunk` is required; pass `undefined` explicitly when it is part of the chunk type.
30+
controller.enqueue();
31+
controller.enqueue(undefined);
32+
controller.close();
33+
},
34+
});
35+
const values: (string | undefined)[] = [];
36+
for await (const chunk of stream) {
37+
values.push(chunk);
38+
}
39+
// enqueue() and enqueue(undefined) should have the same effect
40+
assert.deepStrictEqual(values, [undefined, undefined]);
41+
}
42+
43+
async function transformStreamControllerTreatsExplicitUndefinedAsAChunk() {
44+
const stream = new TransformStream<string, string | undefined>({
45+
transform(chunk, controller) {
46+
assert.strictEqual(chunk, "input");
47+
48+
// @ts-expect-error `chunk` is required; pass `undefined` explicitly when it is part of the chunk type.
49+
controller.enqueue();
50+
controller.enqueue(undefined);
51+
},
52+
});
53+
const values: (string | undefined)[] = [];
54+
for await (const chunk of ReadableStream.from(["input"]).pipeThrough(stream)) {
55+
values.push(chunk);
56+
}
57+
// enqueue() and enqueue(undefined) should have the same effect
58+
assert.deepStrictEqual(values, [undefined, undefined]);
59+
}
60+
61+
async function writableStreamWriterTreatsExplicitUndefinedAsAChunk() {
62+
const writtenChunks: (string | undefined)[] = [];
63+
64+
const stream = new WritableStream<string | undefined>({
65+
write(chunk) {
66+
writtenChunks.push(chunk);
67+
},
68+
});
69+
const writer = stream.getWriter();
70+
// @ts-expect-error `chunk` is required; pass `undefined` explicitly when it is part of the chunk type.
71+
await writer.write();
72+
await writer.write(undefined);
73+
await writer.close();
74+
75+
assert.deepStrictEqual(writtenChunks, [undefined, undefined]);
76+
}
77+
78+
async function queuingStrategySizeReceivesTheChunk() {
79+
const sizeChunks: string[] = [];
80+
81+
const size: QueuingStrategySize<string> = (chunk) => {
82+
// $ExpectType string
83+
chunk;
84+
sizeChunks.push(chunk);
85+
return chunk.length;
86+
};
87+
88+
const stream = new ReadableStream<string>(
89+
{
90+
start(controller) {
91+
controller.enqueue("size");
92+
controller.close();
93+
},
94+
},
95+
{
96+
highWaterMark: 10,
97+
size,
98+
},
99+
);
100+
const result = await stream.getReader().read();
101+
assert.deepStrictEqual(result, { done: false, value: "size" });
102+
assert.deepStrictEqual(sizeChunks, ["size"]);
103+
}

‎types/node/v22/node-tests.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import "./test/repl";
2929
import "./test/sea";
3030
import "./test/sqlite";
3131
import "./test/stream";
32+
import "./test/stream-web";
3233
import "./test/string_decoder";
3334
import "./test/test";
3435
import "./test/timers_promises";

‎types/node/v22/stream/web.d.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ declare module "stream/web" {
109109
}
110110
interface ReadableStreamReadDoneResult<T> {
111111
done: true;
112-
value?: T;
112+
value: T | undefined;
113113
}
114114
type ReadableStreamReadResult<T> = ReadableStreamReadValueResult<T> | ReadableStreamReadDoneResult<T>;
115115
interface ReadableByteStreamControllerCallback {
@@ -254,7 +254,7 @@ declare module "stream/web" {
254254
interface ReadableStreamDefaultController<R = any> {
255255
readonly desiredSize: number | null;
256256
close(): void;
257-
enqueue(chunk?: R): void;
257+
enqueue(chunk: R): void;
258258
error(e?: any): void;
259259
}
260260
const ReadableStreamDefaultController: {
@@ -283,7 +283,7 @@ declare module "stream/web" {
283283
};
284284
interface TransformStreamDefaultController<O = any> {
285285
readonly desiredSize: number | null;
286-
enqueue(chunk?: O): void;
286+
enqueue(chunk: O): void;
287287
error(reason?: any): void;
288288
terminate(): void;
289289
}
@@ -319,7 +319,7 @@ declare module "stream/web" {
319319
abort(reason?: any): Promise<void>;
320320
close(): Promise<void>;
321321
releaseLock(): void;
322-
write(chunk?: W): Promise<void>;
322+
write(chunk: W): Promise<void>;
323323
}
324324
const WritableStreamDefaultWriter: {
325325
prototype: WritableStreamDefaultWriter;
@@ -343,7 +343,7 @@ declare module "stream/web" {
343343
size?: QueuingStrategySize<T>;
344344
}
345345
interface QueuingStrategySize<T = any> {
346-
(chunk?: T): number;
346+
(chunk: T): number;
347347
}
348348
interface QueuingStrategyInit {
349349
/**

0 commit comments

Comments
 (0)