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

fix(fetch): improve Headers and Request type-compatibility #1947

Closed
wants to merge 1 commit into from

Conversation

kettanaito
Copy link
Contributor

@kettanaito kettanaito commented Feb 20, 2023

I'm using a simple reproduction example to test type congruence of Undici against lib/dom:

import { Request as UndiciRequest } from 'undici'

function transform(r: Request): void {}

transform(new UndiciRequest('/hello'))
// ^^^ This won't compile in TypeScript!

@@ -68,7 +68,7 @@ export declare class Headers implements SpecIterable<[string, string]> {
readonly keys: () => SpecIterableIterator<string>
readonly values: () => SpecIterableIterator<string>
readonly entries: () => SpecIterableIterator<[string, string]>
readonly [Symbol.iterator]: () => SpecIterator<[string, string]>
readonly [Symbol.iterator]: () => SpecIterableIterator<[string, string]>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears that the iterator symbol on Headers must be iterable.

@@ -146,7 +146,8 @@ export declare class Request implements BodyMixin {
readonly method: string
readonly mode: RequestMode
readonly redirect: RequestRedirect
readonly referrerPolicy: string
readonly referrer: string
readonly referrerPolicy: ReferrerPolicy
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also narrowing down the referrer policy as we already have the ReferrerPolicy type used for RequestInit. It cannot really be anything else, to my best knowledge.

@@ -146,7 +146,8 @@ export declare class Request implements BodyMixin {
readonly method: string
readonly mode: RequestMode
readonly redirect: RequestRedirect
readonly referrerPolicy: string
readonly referrer: string
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the missing referrer property.

@kettanaito
Copy link
Contributor Author

With these changes, I can eliminate most of the type-related errors in my usage project. However, there seems to be an incongruence between the Request.body types. The ReadableStream<R> type from stream/web is incompatible with the ReadableStream<T> type from lib/dom. Here, I'm hesitant to call stream/web the issue because it looks like lib/dom contains outdated types and has issues raised regarding this (DefinitelyTyped/DefinitelyTyped#58252). Sadly, those were never addressed.

There are a few waves of errors that happen:

1. ReadableStream<any> (Undici) is incompatible with ReadableStream<Uint8Array> (lib/dom)

This can be rather simply addressed by:

-body: ReadableStream | null
+body: ReadableStream<Uint8Array> | null

However, another issues arises from this.

2. ReadableStream<Uint8Array> (Undici*) is not compatible with ReadableStream<Uint8Array>

Argument of type 'import("/undici/types/fetch").Request' is not assignable to parameter of type 'Request'.
  Types of property 'body' are incompatible.
    Type 'import("stream/web").ReadableStream<Uint8Array> | null' is not assignable to type 'ReadableStream<Uint8Array> | null'.
      Type 'import("stream/web").ReadableStream<Uint8Array>' is not assignable to type 'ReadableStream<Uint8Array>'.
        The types returned by 'getReader(...).read(...)' are incompatible between these types.
          Type 'Promise<ReadableStreamDefaultReadResult<Uint8Array>>' is not assignable to type 'Promise<ReadableStreamReadResult<T>>'.
            Type 'ReadableStreamDefaultReadResult<Uint8Array>' is not assignable to type 'ReadableStreamReadResult<T>'.
              Type 'ReadableStreamDefaultReadValueResult<Uint8Array>' is not assignable to type 'ReadableStreamReadResult<T>'.
                Type 'ReadableStreamDefaultReadValueResult<Uint8Array>' is not assignable to type 'ReadableStreamReadValueResult<T>'.
                  Types of property 'value' are incompatible.
                    Type 'Uint8Array' is not assignable to type 'T'.
                      'Uint8Array' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'ArrayBufferView'.

This has to do with proper generics usage, my head is too cloudy right now to remember how to resolve it. Will circle back to it later.

Copy link
Member

@KhafraDev KhafraDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changes look fine, the body type fix can wait for another PR (although ReadableStream<Uint8Array> is correct)

@kettanaito
Copy link
Contributor Author

By the way, I don't mind lending a hand with type testing in this repo. I've worked some time with it and it has proven rather useful. You can see an example of it in here. Basically, with a bit of a configuration, we can automate the type-checking of Undici examples against different versions of TypeScript even, and use those as tests to catch type-related regressions. I think in the light that Undici is not authored in TypeScript, type tests stand twice as useful.

@mcollina
Copy link
Member

By the way, I don't mind lending a hand with type testing in this repo. I've worked some time with it and it has proven rather useful. You can see an example of it in here. Basically, with a bit of a configuration, we can automate the type-checking of Undici examples against different versions of TypeScript even, and use those as tests to catch type-related regressions. I think in the light that Undici is not authored in TypeScript, type tests stand twice as useful.

Any help is appreciated! Go for it.


Can this PR land? It's still marked as draft.

@kettanaito kettanaito marked this pull request as ready for review February 21, 2023 10:47
@kettanaito
Copy link
Contributor Author

Hey, @mcollina. It's ready at its current state. Is it okay that some tests are failing on CI? They also fail for me locally (on main) so I assume that's not related to the changes.

@mcollina
Copy link
Member

I think there was a bug in one of the deps that was fixed.

@mcollina
Copy link
Member

Could you add a test for the types? We use tsd.

@kettanaito
Copy link
Contributor Author

I'm a bit overwhelmed with work, I will add the test this/next week.

@kettanaito kettanaito closed this Feb 22, 2023
@kettanaito
Copy link
Contributor Author

I love GitHub. Let's put two buttons with totally opposite actions 3px away from each other. Sorry, will re-open.

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

Successfully merging this pull request may close these issues.

Fetch types are incompatible with "lib/dom" definitions
3 participants