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

Array.isArray control-flow analysis is confused by readonly arrays #32736

Closed
brandonbloom opened this issue Aug 6, 2019 · 4 comments
Closed
Labels
Duplicate An existing issue was already created

Comments

@brandonbloom
Copy link
Contributor

TypeScript Version: 3.5.3

Search Terms: Array.isArray, readonly, control-flow analysis

Code

type T = string | readonly string[]; // remove "readonly" to make this work

let x: T = 'x' as T;

if (Array.isArray(x)) {
  throw Error('unexpected array');
}

let y: string = x; // error here

Expected behavior:

Array.isArray should influence code-flow analysis even when array is marked readonly.

Actual behavior:

The type after the control-flow throws for array types still reports a union type that supports an array.

Playground Link: https://www.typescriptlang.org/play/index.html#code/C4TwDgpgBAKlC8UDOwBOBLAdgcygHylQgEMATAe0wBsRk0tsBtAXQG4AodqiYKADwBcsBFADkfUVGJJYHdugBmUABQBBVKmIgAdOiTrNIZXwCUJqAG92UKMAAWqcgHcoAUQ3lUy0QFdMEPkgAY2AIUikNLVETDgBfTm5eECEUDBwRPlYgA

Related Issues:

@MartinJohns
Copy link
Contributor

This is a duplicate of #17002. readonly string[] is just another way of writing ReadonlyArray<string>.

@jack-williams
Copy link
Collaborator

The negation of a type-guard works by filtering out all types in the source (here T) which can be assigned to the predicate type. Read-only arrays cannot be assigned to mutable arrays therefore readonly string[] is not filtered from T at x after the conditional.

@RyanCavanaugh
Copy link
Member

Right, having the signature in place from the PR for that issue makes the example in the OP work as anticipated.

That said, this is somewhat fishy? What if you had written

let m: string | Animal = ...;

if (isCat(m)) throw Error("meow");

m; // <--- ?

There's no reason to think that m can't be a Dog ? It seems like the intuition about readonly array is just that's an Array with some special "readonly" bit set that doesn't actually change the type relationship, but that isn't the case.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Aug 6, 2019
@brandonbloom
Copy link
Contributor Author

My bad, I misread that other issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants