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>
.
You need a new version of the Node.js types.
npm update @types/node --save
# 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
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).
Iterable
s (and IterableIterator
s) are nice because they can be used in all sorts of places in JavaScript - but a lot of people found themselves missing methods on Array
s 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 Iterable
s into this new type with Iterable.from
:
Iterator.from(...).filter(someFunction);
Now whenever a built-in method, or a generator, produces one of these IterableIterator
s, 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.