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

ArrayBuffer.isView not narrowing type #57972

Closed
SarahAnnTolsma opened this issue Mar 27, 2024 · 3 comments
Closed

ArrayBuffer.isView not narrowing type #57972

SarahAnnTolsma opened this issue Mar 27, 2024 · 3 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@SarahAnnTolsma
Copy link

🔎 Search Terms

ArrayBuffer, ArrayBuffer.isView, type narrow

🕗 Version & Regression Information

This is the behavior in every version I tried, including the nightly version.

I've reviewed the FAQ on type narrowing, but I do not believe it applies to the issue at hand. It could be related to https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-isfoox-narrow-x-to-foo-when-isfoo-is-a-type-guard, but given that the section is not filled out ("TODO") it is unclear whether this is the same issue.

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.5.0-dev.20240327#code/GYVwdgxgLglg9mABMOcAUATAhlLAuRAZygCcYwBzRAH0QFVyoAOAQRJKwE8bE2POAQiGDAApiQCUBMCAC2AI3EAoAN5LEGxDGCI0UTgAdRcHdlyIAvFcQAiYmUo2J6zWs3vEZrJcRhRAd0QAFVEADygAUUg4DHE0CQA6UWjYzBwsCQBuFw0AXxzEUQAbQlEtHTQAQj4uIRFxBJhCADUYALTcCWd3Nw8NLx8-QIYwZhrODozs93z3AoB6ed4oRCgACybEAzhGABpEAAMvA8QAfUI1uBAijFPERXpGVnYufcUILBBS3hfBYTESI0Wm1-PFECRRFAQCQwIRDsAsCVRCcUCRDuM6gCEogAJKwqCiLAYfZHdInTbEGBFIqrQyiDCILBwg4jMa-HgY-7iA4JAoQqEwzzpBJFZIUdbZXJAA

💻 Code

function foo(data: string | Uint8Array | ArrayBuffer): number
{
    if (typeof data === "string")
    {
        data = new TextEncoder().encode(data);
    }
    else if (!ArrayBuffer.isView(data))
    {
        data = new Uint8Array(data);
    }
    
    // At this point, `data` _should_ be Uint8Array, because ArrayBuffer.isView() returns `false` for `ArrayBuffer. Instead, `data` is still typed as `Uint8Array | ArrayBuffer`.
    return data.length;
}

🙁 Actual behavior

The data variable is not being narrowed to a Uint8Array by the time it reaches the return statement. This is causing both an Intellisense error, as well as a build error.

🙂 Expected behavior

In the above code, I would expect data to be correctly narrowed to a UInt8Array by the time we reach the return line. Given that ArrayBuffer.isView() returns true for Uint8Array and false for ArrayBuffer, the if / else if guarantees that data must be Uint8Array at the return.

I can confirm this behavior by running the code as plain JS in the DevTools console:

function foo(data)
{
    if (typeof data === "string")
    {
        console.log("string");
        data = new TextEncoder().encode(data);
    }
    else if (!ArrayBuffer.isView(data))
    {
        console.log("arraybuffer");
        data = new Uint8Array(data);
    }
    else
    {
        console.log("uint8array");
    }
    
    return data.length;
}

< foo("hello")
> string
> 5
< foo(new Uint8Array())
> uint8array
> 0
< foo(new Uint8Array().buffer)
> arraybuffer
> 0

Additional information about the issue

No response

@RyanCavanaugh
Copy link
Member

In the above code, I would expect data to be correctly narrowed to a UInt8Array by the time we reach the return line. Given that ArrayBuffer.isView() returns true for Uint8Array and false for ArrayBuffer,

The problem is that it's possible (from a structural typing point of view) that data is an ArrayBuffer & ArrayBufferView, in which case isView would return true for a value inhabiting the ArrayBuffer part of the union.

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Mar 27, 2024
@fatcerberus
Copy link

@RyanCavanaugh Is that related to the typed-array types being structurally compatible with ArrayBuffer (a complaint for which there are several existing issues that I don't feel like looking up at present)

@typescript-bot
Copy link
Collaborator

This issue has been marked as "Working as Intended" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Mar 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants