Ao converter valores primitivos como strings ou até objetos em ReadableStream, um caminho comum é transformar tudo em Blob primeiro.
O problema é que, quando o stream é gerado a partir de Blob, ele vira Uint8Array. Isso não é necessariamente errado, e para operações binárias provavelmente é até o caminho mais eficiente.
Mesmo assim, eu queria uma pequena função utilitária que também pudesse tratar strings e outros valores diretamente, então resolvi escrever uma.
Código
type StreamResource<T> = T extends Blob ? Uint8Array : T extends Uint8Array | ArrayBuffer ? Uint8Array : T extends undefined | null | symbol ? never : T;
function toReadableStream<T>(value: T): ReadableStream<StreamResource<T>> { if (value === undefined || value === null || typeof value === "symbol") { throw new TypeError( "Cannot convert undefined, null, or symbol to ReadableStream" ); }
if (value instanceof Blob) { return value.stream() as ReadableStream<StreamResource<T>>; }
if (value instanceof Uint8Array || value instanceof ArrayBuffer) { const uint8Array = new Uint8Array(value); return new ReadableStream<Uint8Array>({ start(controller) { controller.enqueue(uint8Array); controller.close(); }, }) as ReadableStream<StreamResource<T>>; }
return new ReadableStream<StreamResource<T>>({ start(controller) { controller.enqueue(value as StreamResource<T>); controller.close(); }, });}Exemplos de uso
const blob = new Blob(['Hello, World!'], { type: 'text/plain' });const blobStream = toReadableStream(blob);// ^? ReadableStream<Uint8Array>
const buffer = new ArrayBuffer(8);const bufferStream = toReadableStream(buffer);// ^? ReadableStream<Uint8Array>
const uint8Array = new Uint8Array([1, 2, 3, 4]);const uint8ArrayStream = toReadableStream(uint8Array);// ^? ReadableStream<Uint8Array>
const str = 'Hello, TypeScript!';const strStream = toReadableStream(str);// ^? ReadableStream<string>
const num = 42;const numStream = toReadableStream(num);// ^? ReadableStream<number>
const undefStream = toReadableStream(undefined);// ^? ReadableStream<never>Pontos
- Usa Conditional Types para uma conversão segura em termos de tipo
BlobeArrayBufferviram streams deUint8Arraystring,numbere valores parecidos permanecem com o tipo originalundefined,nullesymbolsão tratados como erro de tipo
Resumo
Ao fazer enqueue de valores diretamente em um ReadableStream, fica possível montar streams de forma mais flexível do que sempre passando por Blob.
A inferência de tipos também funciona bem, então essa utilidade acaba sendo prática no dia a dia com TypeScript.
hsb.horse