37

Trying to upgrade to TypeScript 5.6 Beta, I get the following error messages in node_modules. I didn't make any other change, so what should I do to fix these errors?

node_modules/@types/node/buffer.d.ts:632:19 - error TS2430: Interface 'Buffer' incorrectly extends interface 'Uint8Array'.
  The types returned by 'reverse()' are incompatible between these types.
    Type 'this' is not assignable to type 'Uint8Array'.
      Type 'Buffer' is not assignable to type 'Uint8Array'.
        The types returned by 'slice(...).entries()' are incompatible between these types.
          Type 'IterableIterator<[number, number]>' is missing the following properties from type 'BuiltinIterator<[number, number], undefined, any>': map, filter, take, drop, and 8 more.

632         interface Buffer extends Uint8Array {
                      ~~~~~~
node_modules/@types/node/fs/promises.d.ts:56:66 - error TS2344: Type 'Buffer' does not satisfy the constraint 'ArrayBufferView'.
  Type 'Buffer' is not assignable to type 'Uint8Array | DataView'.
    Type 'Buffer' is not assignable to type 'Uint8Array'.
      The types returned by 'entries()' are incompatible between these types.
        Type 'IterableIterator<[number, number]>' is missing the following properties from type 'BuiltinIterator<[number, number], undefined, any>': map, filter, take, drop, and 8 more.

56     interface FileReadOptions<T extends NodeJS.ArrayBufferView = Buffer> {
                                                                    ~~~~~~
node_modules/@types/node/fs/promises.d.ts:238:49 - error TS2344: Type 'Buffer' does not satisfy the constraint 'ArrayBufferView'.
  Type 'Buffer' is not assignable to type 'Uint8Array | DataView'.
    Type 'Buffer' is not assignable to type 'Uint8Array'.
      The types returned by 'entries()' are incompatible between these types.
        Type 'IterableIterator<[number, number]>' is missing the following properties from type 'BuiltinIterator<[number, number], undefined, any>': map, filter, take, drop, and 8 more.

238         read<T extends NodeJS.ArrayBufferView = Buffer>(options?: FileReadOptions<T>): Promise<FileReadResult<T>>;
                                                    ~~~~~~

Note: when I used a newer version of TypeScript 5.6, mentions of BuiltinIterator<[number, number], ...> seem replaced with ArrayIterator<number>.

1 Answer 1

64

Short Answer

You need a new version of the Node.js types.

npm update @types/node --save-dev

# or if you need a specific version
npm install -D @types/node@16
npm install -D @types/node@18
npm install -D @types/node@20
npm install -D @types/node@22

Long Answer

First, IterableIterator describes a type that is both Iterable (it can create an Iterator by calling someValue[Symbol.iterator()]), and is itself an Iterator (you can call things like next() on it over and over until it's out of values).

Iterables (and IterableIterators) are nice because they can be used in all sorts of places in JavaScript - but a lot of people found themselves missing methods on Arrays like map, filter, etc. So a recent proposal was brought forward in JavaScript/ECMAScript to bring many useful methods from Array (plus a few more). You can adapt any existing Iterables into this new type with Iterable.from:

Iterator.from(...).filter(someFunction);

Now whenever a built-in method, or a generator, produces one of these IterableIterators, it is backed by the methods on Iterator.prototype, and you can call something like map, filter, etc.

new Uint8Array(100).entries().map(x => x)

Notice though that we're talking about a new runtime value called Iterator. You can reference Iterator and Iterator.prototype as actual values in JavaScript. This is a bit awkward since TypeScript defines its own thing called Iterator that exists purely for type-checking. So due to this unfortunate name clash, TypeScript needs to introduce a separate type to describe these built-in iterable iterators.

TypeScript 5.6 introduces a new type called IteratorObject (and a few subtypes like ArrayIterator). Lots of built-in collections and methods produce this type, so many methods had to be updated to produce it.

So how does this cause problems in Node.js? Well in @types/node, Buffer is basically a subtype of Uint8Array. Buffer unnecessarily redeclared the entries() method in a way that copied the old signature:

    /**
     * Returns an array of key, value pairs for every entry in the array
     */
    entries(): IterableIterator<[number, number]>;
}

However, in TypeScript 5.6, Uint8Array has been updated to use a signature like:

    entries(): ArrayIterator<number>;
}

This caused the two to diverge in slightly incompatible ways.

So recently, @types/node has been updated to avoid the issue entirely.

Sign up to request clarification or add additional context in comments.

4 Comments

Hi Daniel, thanks for the elaborate answer! Do you know whether there is any way (or are there any plans) to backport this fix to the current LTS version of Node (= Node 20)?
@balu, the change was actually backported to versions going back to Node 16. I believe you can get a more appropriate version by updating @types/node@16, @types/node@18, @types/node@20, etc.
Ah, now there's indeed an update! Thanks so much, Daniel, the "IterableIterator vs. BuiltinIterator" error has now disappeared! However, I'm still struggling with a second type error in my code which to me sounds related to what you wrote above, maybe you could have a look?
i had to update my @types/node to the latest @20 !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.