uhop / stream-chain

Chain functions as transform streams.
BSD 3-Clause "New" or "Revised" License
84 stars 11 forks source link

Error in typescript #23

Open comman-fukui opened 1 week ago

comman-fukui commented 1 week ago

If the fns argument of the chain function is an array of two or more arrays, an error occurs in the typescript environment. For example, the “Intro” sample in README.md will generate the following error

Error: Argument of type '[(x: any) => number, (x: any) => Many, (x: any) => Generator<any, number, unknown>, (x: any) => any, Transform, (x: any) => string, Gzip]' is not assignable to parameter of type 'readonly [any]'. Source has 7 element(s) but target allows only 1.

This problem did not exist until version 3.1.0, and has been occurring since version 3.2.0.

uhop commented 1 week ago

Could you share the (hopefully) minimal code that shows the error? It'll speed up the fix.

comman-fukui commented 3 days ago

@uhop Sorry for the delay. I created a reproduction repository. https://github.com/comman-fukui/issue-stream-chain-typescript

git clone git@github.com:comman-fukui/issue-stream-chain-typescript.git
cd issue-stream-chain-typescript
pnpm install
pnpm run build

> issue-stream-chain-typescript@1.0.0 build /home/comman/dev/_experiment/issue-stream-chain-typescript
> tsc

index.ts:8:24 - error TS2345: Argument of type '[(x: any) => number, (x: any) => Many<any>, (x: any) => Generator<any, number, unknown>, (x: any) => any, Transform, (x: any) => string, Gzip]' is not assignable to parameter of type 'readonly [any]'.
  Source has 7 element(s) but target allows only 1.

  8 const pipeline = chain([
                           ~
  9   // transforms a value
    ~~~~~~~~~~~~~~~~~~~~~~~
... 
 38   zlib.createGzip()
    ~~~~~~~~~~~~~~~~~~~
 39 ]);

If the length of the array of arguments passed to chain is one, there is no error, but if there are two or more, an error occurs.

nazar commented 2 days ago

I am also seeing this on TS 5.5.4 and for me the fix was to specify the chain input array as a const:

    const reportPipeline = chain([
      batchedStream,
      dbRowsTransformStream,
      dataStreamRowsTransposeTransform,
      reportGeneratorStream
    ] as const);

Otherwise, I was seeing this:

Screenshot 2024-11-19 at 13 39 00

HTH and thank you for the library!!1

uhop commented 2 days ago

In TypeScript, you can use the as const assertion to create a readonly tuple from an array literal. This ensures that the types of the elements and the length of the tuple are preserved.

Yes, users should use as const (on the external array) to enable type checking on chained streams/functions. Without this cast TS assumes an array of homogeneous values, e.g., any, which defeats the purpose of type checks. Adding an array as a valid signature suppresses errors from other alternatives.

If somebody knows a better way of doing chained type validations, please contribute the code for that.

It looks like this TS point should be highlighted in the documentation.

PS: The demo for using this library with TS: https://github.com/uhop/stream-chain/blob/master/ts-test/demo.mts

PPS: Obviously, anyone can opt-out of type checks by using JS.

comman-fukui commented 1 day ago

Thank you all for your answers. Personally, if using "as const" avoids the error, I don't think it's a problem. It would be even better if the documentation said so.

comman-fukui commented 1 day ago

On another note, I found another typing issue. I pushed the reproduced code to the following git branch. https://github.com/comman-fukui/issue-stream-chain-typescript/tree/issue-union-type

If what is passed to the chain function is a Chain or Parser type, no error occurs, but if it is a union of Chain and Parser, an error occurs. I have looked to see how the type definition should be modified, but I am not sure...

(Should I create another issue?)