Skip to content

Instantly share code, notes, and snippets.

@benhatsor
Last active June 2, 2026 16:15
Show Gist options
  • Select an option

  • Save benhatsor/5029747bc5900906ee67c46e81259dff to your computer and use it in GitHub Desktop.

Select an option

Save benhatsor/5029747bc5900906ee67c46e81259dff to your computer and use it in GitHub Desktop.
A simple wrapper for TransformStream.
/**
* A simple wrapper for `TransformStream`.
* @example
* class UpperCaseStream extends TransformStreamInterface<string, string> {
* transform(chunk: string) {
* return chunk.toUpperCase()
* }
* }
*
* // Usage:
* const response = await fetch('./lorem-ipsum.txt')
* if (!response.ok || !response.body) throw new Error('Request failed')
* const stream = response.body
* .pipeThrough(new TextDecoderStream())
* .pipeThrough(new UpperCaseStream())
* // Baseline Newly Available (Safari 26.4+):
* let fullText = ''
* for await (const chunk of stream) {
* fullText += chunk
* }
* console.log(fullText)
*/
abstract class TransformStreamInterface<I, O> extends TransformStream<I, O> {
constructor() {
super({
transform: (chunk: I, controller: TransformStreamDefaultController<O>) =>
this.internalTransform(chunk, controller)
})
}
private async internalTransform(chunk: I, controller: TransformStreamDefaultController<O>) {
try {
const transformedChunk = await this.transform(chunk)
if (transformedChunk === null) { return }
controller.enqueue(transformedChunk)
} catch (error) {
controller.error(error)
}
}
/** Transform the chunk. Return `null` to skip it. */
protected abstract transform(chunk: I): (O | null) | Promise<O | null>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment