Quand on veut convertir des valeurs primitives comme des chaînes, ou même des objets, en ReadableStream, une méthode courante consiste à passer d’abord par Blob.
Le problème, c’est qu’un flux généré via Blob devient un flux de Uint8Array. Ce n’est pas forcément une erreur, et pour des opérations binaires c’est probablement la voie la plus efficace.
Malgré cela, je voulais une petite fonction utilitaire capable de traiter directement des chaînes et d’autres types de valeurs, alors je l’ai écrite.
Code
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(); }, });}Exemples d’utilisation
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>Points clés
- Conversion typée avec les Conditional Types
BlobetArrayBufferdeviennent des flux deUint8Array- Les
string,numberet autres types similaires restent tels quels undefined,nulletsymbolsont traités comme des erreurs de type
Résumé
En envoyant directement les valeurs dans un ReadableStream, on obtient une création de flux plus souple qu’en passant systématiquement par Blob.
L’inférence de types fonctionne bien aussi, donc cela devient une utilité pratique en TypeScript.
hsb.horse