Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AsyncIterator type is not covariant #103

Open
Peeja opened this issue Aug 11, 2023 · 1 comment
Open

AsyncIterator type is not covariant #103

Peeja opened this issue Aug 11, 2023 · 1 comment
Assignees

Comments

@Peeja
Copy link

Peeja commented Aug 11, 2023

I would have expected the AsyncIterator type to be covariant; that is, I would expect to be able to do something like:

declare const oneIterator: AsyncIterator<1>;
const numberIterator: AsyncIterator<number> = oneIterator;

However, this fails because:

Type 'AsyncIterator<1>' is not assignable to type 'AsyncIterator<number>'.
  Types of property 'transform' are incompatible.
    Type '<D>(options: TransformOptions<1, D>) => AsyncIterator<D>' is not assignable to type '<D>(options: TransformOptions<number, D>) => AsyncIterator<D>'.
      Types of parameters 'options' and 'options' are incompatible.
        Type 'TransformOptions<number, any>' is not assignable to type 'TransformOptions<1, any>'.
          Types of property 'source' are incompatible.
            Type 'SourceExpression<number> | undefined' is not assignable to type 'SourceExpression<1> | undefined'.
              Type 'AsyncIterator<number>' is not assignable to type 'SourceExpression<1> | undefined'.
                Type 'AsyncIterator<number>' is not assignable to type 'AsyncIterator<1>'.
                  The types returned by 'read()' are incompatible between these types.
                    Type 'number | null' is not assignable to type '1 | null'.
                      Type 'number' is not assignable to type '1'. ts(2322)

I'm inexperienced with AsyncIterator, so I'm not completely following what that error amounts to. It looks to me like it's complaining that you could call numberIterator.transform({ source: anotherNumberIterator }), and since anotherNumberIterator emits numbers, but numberIterator (which is secretly also oneIterator) is only expecting 1s, not other numbers.

Except, I don't understand why you'd provide numberIterator.transform() with a source option. Isn't numberIterator itself the source? I'm not clear why that option is available or what it means to provide it. It doesn't appear to be documented.

@joachimvh
Copy link
Collaborator

Not exactly sure why @RubenVerborgh assigned me this issue as I haven't worked with this library for several years. Maybe because I like typings.

But no, AsyncIterator<1> can not be assigned to AsyncIterator<number>. Reason being that an AsyncIterator is both an inpud and output stream. I'm not sure exactly what is causing the issue with the transform function but, for example, if you would remove that one the next function TS is going to complain about is the prepend function, as that one is used to input data into the iterator. In the case of AsyncIterator<1> that function only accepts 1 values, but to become a AsyncIterator<number> it would have to accept all numbers, and there is no guarantee that it would be able to do that.

What you can do is transform a AsyncIterator<1> into a AsyncIterator<number> with

const numberIterator: AsyncIterator<number> = new SimpleTransformIterator(oneIterator);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants