Microsoft/TypeScript

Generic TypedArray constructors have only one overload

Open

#61,680 opened on May 9, 2025

View on GitHub
 (3 comments) (0 reactions) (0 assignees)TypeScript (48,455 stars) (6,726 forks)batch import
Domain: lib.d.tsHelp WantedPossible Improvement

Description

🔎 Search Terms

Uint8Array

🕗 Version & Regression Information

  • This is the behavior in versions 5.8.3 and 5.7.3
  • I was unable to test this on prior versions because Uint8Array is not generic in earlier versions

⏯ Playground Link

https://www.typescriptlang.org/play/?target=11&ts=5.8.3#code/MYewdgzgLgBBIFcBOwCmMC8MyoO4wFUBLMKADgEEkkBDATwAoBGABgEoBuAKC9EllAAHOk0zY8hEuSq1G8ZGk69w0GELoAmMTnzFSlavQA8M+gCEEAM0uokAGSIBrVAD4G8lKiV9V6gMzaEnrShnQmoRbWtm4eitxAA

💻 Code

const source = new Uint8Array(10);

const copy1 = new Uint8Array(source); // OK
const copy2 = new Uint8Array<ArrayBufferLike>(source); // TS 2345
const copy3 = new Uint8Array<ArrayBuffer>(source); // TS 2345

🙁 Actual behavior

Only the generic constructor overload of Uint8Array is available when using Uint8Array with a generic parameter, i.e. the one which accepts a TArrayBuffer as the first argument. It is therefore not possible to pass a Uint8Array as the first argument without a compile error, even though this is valid.

🙂 Expected behavior

It should be possible to use all the valid overloads of Uint8Array (and friends) constructor without a compiler error.

Additional information about the issue

This seems to only affect target value of ES2024 or ESNext, but I can't figure out why from looking at the types.

I assume this behaviour occurs for the same reason as given in this comment. In that case I assume the fix would be adding copies of all the constructor overloads to the Uint8ArrayConstructor interface, but with type parameters.

For example, the following works (TS Playground):

interface Uint8ArrayConstructor {
    // this is just a copy of existing overloads, with `TArrayBuffer` param added
    new <TArrayBuffer extends ArrayBufferLike = ArrayBuffer>(
      length: number,
    ): Uint8Array<TArrayBuffer>;
    new <TArrayBuffer extends ArrayBufferLike = ArrayBuffer>(
      array: ArrayLike<number>,
    ): Uint8Array<TArrayBuffer>;
    new <TArrayBuffer extends ArrayBufferLike = ArrayBuffer>(
      buffer: ArrayBuffer,
      byteOffset?: number,
      length?: number,
    ): Uint8Array<TArrayBuffer>;
    new <TArrayBuffer extends ArrayBufferLike = ArrayBuffer>(
      array: ArrayLike<number> | ArrayBuffer,
    ): Uint8Array<TArrayBuffer>;
}

const source = new Uint8Array(10);

const copy1 = new Uint8Array(source);
const copy2 = new Uint8Array<ArrayBufferLike>(source);
const copy3 = new Uint8Array<ArrayBuffer>(source);

I think this is basically the opposite problem to that which was fixed by #60934.

Contributor guide