@@ -17,6 +17,52 @@ import {
1717} from './utils' ;
1818import type { StreamablePatch , StreamableValue } from './types' ;
1919
20+ // It's necessary to define the type manually here, otherwise TypeScript compiler
21+ // will not be able to infer the correct return type as it's circular.
22+ type StreamableUIWrapper = {
23+ /**
24+ * The value of the streamable UI. This can be returned from a Server Action and received by the client.
25+ */
26+ readonly value : React . ReactNode ;
27+
28+ /**
29+ * This method updates the current UI node. It takes a new UI node and replaces the old one.
30+ */
31+ update ( value : React . ReactNode ) : StreamableUIWrapper ;
32+
33+ /**
34+ * This method is used to append a new UI node to the end of the old one.
35+ * Once appended a new UI node, the previous UI node cannot be updated anymore.
36+ *
37+ * @example
38+ * ```jsx
39+ * const ui = createStreamableUI(<div>hello</div>)
40+ * ui.append(<div>world</div>)
41+ *
42+ * // The UI node will be:
43+ * // <>
44+ * // <div>hello</div>
45+ * // <div>world</div>
46+ * // </>
47+ * ```
48+ */
49+ append ( value : React . ReactNode ) : StreamableUIWrapper ;
50+
51+ /**
52+ * This method is used to signal that there is an error in the UI stream.
53+ * It will be thrown on the client side and caught by the nearest error boundary component.
54+ */
55+ error ( error : any ) : StreamableUIWrapper ;
56+
57+ /**
58+ * This method marks the UI node as finalized. You can either call it without any parameters or with a new UI node as the final state.
59+ * Once called, the UI node cannot be updated or appended anymore.
60+ *
61+ * This method is always **required** to be called, otherwise the response will be stuck in a loading state.
62+ */
63+ done ( ...args : [ React . ReactNode ] | [ ] ) : StreamableUIWrapper ;
64+ } ;
65+
2066/**
2167 * Create a piece of changable UI that can be streamed to the client.
2268 * On the client side, it can be rendered as a normal React node.
@@ -47,14 +93,8 @@ function createStreamableUI(initialValue?: React.ReactNode) {
4793 }
4894 warnUnclosedStream ( ) ;
4995
50- const streamable = {
51- /**
52- * The value of the streamable UI. This can be returned from a Server Action and received by the client.
53- */
96+ const streamable : StreamableUIWrapper = {
5497 value : row ,
55- /**
56- * This method updates the current UI node. It takes a new UI node and replaces the old one.
57- */
5898 update ( value : React . ReactNode ) {
5999 assertStream ( '.update()' ) ;
60100
@@ -75,22 +115,6 @@ function createStreamableUI(initialValue?: React.ReactNode) {
75115
76116 return streamable ;
77117 } ,
78- /**
79- * This method is used to append a new UI node to the end of the old one.
80- * Once appended a new UI node, the previous UI node cannot be updated anymore.
81- *
82- * @example
83- * ```jsx
84- * const ui = createStreamableUI(<div>hello</div>)
85- * ui.append(<div>world</div>)
86- *
87- * // The UI node will be:
88- * // <>
89- * // <div>hello</div>
90- * // <div>world</div>
91- * // </>
92- * ```
93- */
94118 append ( value : React . ReactNode ) {
95119 assertStream ( '.append()' ) ;
96120
@@ -105,10 +129,6 @@ function createStreamableUI(initialValue?: React.ReactNode) {
105129
106130 return streamable ;
107131 } ,
108- /**
109- * This method is used to signal that there is an error in the UI stream.
110- * It will be thrown on the client side and caught by the nearest error boundary component.
111- */
112132 error ( error : any ) {
113133 assertStream ( '.error()' ) ;
114134
@@ -120,12 +140,6 @@ function createStreamableUI(initialValue?: React.ReactNode) {
120140
121141 return streamable ;
122142 } ,
123- /**
124- * This method marks the UI node as finalized. You can either call it without any parameters or with a new UI node as the final state.
125- * Once called, the UI node cannot be updated or appended anymore.
126- *
127- * This method is always **required** to be called, otherwise the response will be stuck in a loading state.
128- */
129143 done ( ...args : [ ] | [ React . ReactNode ] ) {
130144 assertStream ( '.done()' ) ;
131145
@@ -209,6 +223,59 @@ function createStreamableValue<T = any, E = any>(
209223 return streamableValue ;
210224}
211225
226+ // It's necessary to define the type manually here, otherwise TypeScript compiler
227+ // will not be able to infer the correct return type as it's circular.
228+ type StreamableValueWrapper < T , E > = {
229+ /**
230+ * The value of the streamable. This can be returned from a Server Action and
231+ * received by the client. To read the streamed values, use the
232+ * `readStreamableValue` or `useStreamableValue` APIs.
233+ */
234+ readonly value : StreamableValue < T , E > ;
235+
236+ /**
237+ * This method updates the current value with a new one.
238+ */
239+ update ( value : T ) : StreamableValueWrapper < T , E > ;
240+
241+ /**
242+ * This method is used to append a delta string to the current value. It
243+ * requires the current value of the streamable to be a string.
244+ *
245+ * @example
246+ * ```jsx
247+ * const streamable = createStreamableValue('hello');
248+ * streamable.append(' world');
249+ *
250+ * // The value will be 'hello world'
251+ * ```
252+ */
253+ append ( value : T ) : StreamableValueWrapper < T , E > ;
254+
255+ /**
256+ * This method is used to signal that there is an error in the value stream.
257+ * It will be thrown on the client side when consumed via
258+ * `readStreamableValue` or `useStreamableValue`.
259+ */
260+ error ( error : any ) : StreamableValueWrapper < T , E > ;
261+
262+ /**
263+ * This method marks the value as finalized. You can either call it without
264+ * any parameters or with a new value as the final state.
265+ * Once called, the value cannot be updated or appended anymore.
266+ *
267+ * This method is always **required** to be called, otherwise the response
268+ * will be stuck in a loading state.
269+ */
270+ done ( ...args : [ T ] | [ ] ) : StreamableValueWrapper < T , E > ;
271+
272+ /**
273+ * @internal This is an internal lock to prevent the value from being
274+ * updated by the user.
275+ */
276+ [ STREAMABLE_VALUE_INTERNAL_LOCK ] : boolean ;
277+ } ;
278+
212279function createStreamableValueImpl < T = any , E = any > ( initialValue ?: T ) {
213280 let closed = false ;
214281 let locked = false ;
@@ -286,25 +353,13 @@ function createStreamableValueImpl<T = any, E = any>(initialValue?: T) {
286353 currentValue = value ;
287354 }
288355
289- const streamable = {
290- /**
291- * @internal This is an internal lock to prevent the value from being
292- * updated by the user.
293- */
356+ const streamable : StreamableValueWrapper < T , E > = {
294357 set [ STREAMABLE_VALUE_INTERNAL_LOCK ] ( state : boolean ) {
295358 locked = state ;
296359 } ,
297- /**
298- * The value of the streamable. This can be returned from a Server Action and
299- * received by the client. To read the streamed values, use the
300- * `readStreamableValue` or `useStreamableValue` APIs.
301- */
302360 get value ( ) {
303361 return createWrapped ( true ) ;
304362 } ,
305- /**
306- * This method updates the current value with a new one.
307- */
308363 update ( value : T ) {
309364 assertStream ( '.update()' ) ;
310365
@@ -319,18 +374,6 @@ function createStreamableValueImpl<T = any, E = any>(initialValue?: T) {
319374
320375 return streamable ;
321376 } ,
322- /**
323- * This method is used to append a delta string to the current value. It
324- * requires the current value of the streamable to be a string.
325- *
326- * @example
327- * ```jsx
328- * const streamable = createStreamableValue('hello');
329- * streamable.append(' world');
330- *
331- * // The value will be 'hello world'
332- * ```
333- */
334377 append ( value : T ) {
335378 assertStream ( '.append()' ) ;
336379
@@ -366,11 +409,6 @@ function createStreamableValueImpl<T = any, E = any>(initialValue?: T) {
366409
367410 return streamable ;
368411 } ,
369- /**
370- * This method is used to signal that there is an error in the value stream.
371- * It will be thrown on the client side when consumed via
372- * `readStreamableValue` or `useStreamableValue`.
373- */
374412 error ( error : any ) {
375413 assertStream ( '.error()' ) ;
376414
@@ -385,14 +423,6 @@ function createStreamableValueImpl<T = any, E = any>(initialValue?: T) {
385423
386424 return streamable ;
387425 } ,
388- /**
389- * This method marks the value as finalized. You can either call it without
390- * any parameters or with a new value as the final state.
391- * Once called, the value cannot be updated or appended anymore.
392- *
393- * This method is always **required** to be called, otherwise the response
394- * will be stuck in a loading state.
395- */
396426 done ( ...args : [ ] | [ T ] ) {
397427 assertStream ( '.done()' ) ;
398428
0 commit comments