Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | import stream, { Transform } from "stream";
/**
* This is the basic setup for the Streams
*/
interface ReadableStream<T> extends stream.Readable {
push(chunk: T, encoding?: BufferEncoding): boolean;
read(size?: number): T;
}
interface WritableStream<T> extends stream.Writable {
_write(chunk: T, encoding: BufferEncoding, callback?: ErrorCallback): void;
write(chunk: T, callback?: (error: Error | null | undefined) => void): boolean;
write(chunk: T, encoding: BufferEncoding, callback?: (error: Error | null | undefined) => void): boolean;
}
interface TransformStream<T, U> extends stream.Duplex {
_write(chunk: T, encoding: BufferEncoding, callback?: ErrorCallback): void;
write(chunk: T, callback?: (error: Error | null | undefined) => void): boolean;
write(chunk: T, encoding: BufferEncoding, callback?: (error: Error | null | undefined) => void): boolean;
push(chunk: U, encoding?: BufferEncoding): boolean;
read(size?: number): U;
}
/**
* Functions to pipe, source, transform, and sink
*/
function pipe<T1, T2>(_read: ReadableStream<T1>, _t1: TransformStream<T1, T2>, _write: WritableStream<T2>, _errorCallback?: ErrorCallback): WritableStream<T2> {
throw new Error();
}
function pipeAsync<T1, T2>(_read: ReadableStream<T1>, _t1: TransformStream<T1, T2>, _write: WritableStream<T2>): Promise<void> {
throw new Error();
}
function through<T, U>(
_transform?: (this: TransformStream<T, U>, obj: T, done: (err?: Error | null, data?: U) => void) => void,
_flush?: (this: TransformStream<T, U>, flushCallback: (err?: Error | null, data?: U) => void) => any)
: TransformStream<T, U> {
throw new Error();
}
function throughAsync<T, U>(
_transform?: (this: TransformStream<T, U>, obj: T) => Promise<U>,
_flush?: (this: TransformStream<T, U>) => Promise<U>)
: TransformStream<T, U> {
throw new Error();
}
function source<T>(): ReadableStream<T> {
throw new Error();
}
function sink<T>(): WritableStream<T> {
throw new Error();
}
/**
* Basic Data to pass down the pipe
*/
interface MyOldData {
a: number;
}
interface MyNewData {
b: string;
}
interface MyBadData {
c: string;
}
/**
* The Code
*/
// The through type get inferred as <MyOldData, unknown>
// MyNewData is assignable to unknown so the sink is happy
// But the through is actually passing on a different type MyBadData
pipe(
source<MyOldData>(),
through((data, done) => {
let newData: MyBadData = { c: data.a.toString() }; // <= Not the required type for the sink but no error. I believe because pipe is using `unknown`
done(null, newData);
}),
sink<MyNewData>()
);
pipe(
source<MyOldData>(),
throughAsync((data) => {
let newData: MyBadData = { c: data.a.toString() }; // <= Not the required type for the sink but no error. I believe because pipe is using `unknown`
return Promise.resolve(newData);
}),
sink<MyNewData>()
);
// If I explicitly add the type to through it catches the error when calling done
// Is there a way set it up so that through infers the correct type?
pipe(
source<MyOldData>(),
through<MyOldData, MyNewData>((data, done) => {
let newData: MyBadData = { c: data.a.toString() };
done(null, newData);
}),
sink<MyNewData>()
);
// If the through inferred the type being passed to done it would catch it with the sink
pipe(
source<MyOldData>(),
through<MyOldData, MyBadData>((data, done) => {
let newData: MyBadData = { c: data.a.toString() };
done(null, newData);
}),
sink<MyNewData>()
);
pipe<MyOldData, MyNewData>(
source(),
through((data, done) => {
let newData: MyBadData = { c: data.a.toString() }; // <= Not the required type for the sink but no error. I believe because pipe is using `unknown`
done(null, newData);
}),
sink()
);
// correct Working example
pipe(
source<MyOldData>(),
through<MyOldData, MyNewData>((data, done) => {
let newData: MyNewData = { b: data.a.toString() };
done(null, newData);
}),
sink<MyNewData>()
);
|