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

Issue with Array.isArray typeguard after upgrading from 4.1.2 to 4.1.3 #41984

Closed
mwgamble opened this issue Dec 16, 2020 · 6 comments
Closed
Assignees
Labels
Bug A bug in TypeScript Has Repro This issue has compiler-backed repros: https://aka.ms/ts-repros

Comments

@mwgamble
Copy link

mwgamble commented Dec 16, 2020

TypeScript Version: 4.2.0-dev.20201211

Search Terms:

re: Array.isArray

Code

interface TestCase<T extends string | number> {
    readonly val1: T | ReadonlyArray<T>;
    readonly val2: ReadonlyArray<T>;
}

interface MultiCaseFixture<T> {
    cases: T[];
}

function subDataFunc(): TestCase<string | number>[] {
    return [
        { val1: "a", val2: ["a", "b", "c"] },
        { val1: 2, val2: [1, 2, 3] },
        { val1: ["a", "z"], val2: ["x", "y", "z"] },
        { val1: [5, 10], val2: [10, 100, 1000] },
    ];
}

function dataFunc<T>(subFunc: () => T[]): MultiCaseFixture<T> {
    return { cases: subFunc() };
}

function testFunc() {
    const fixture = dataFunc<TestCase<string | number>>(subDataFunc);
    fixture.cases.forEach(({ val1, val2 }) => {
        if (Array.isArray(val1)) {
            const reversedVal1 = val1.slice().reverse();
            console.log(reversedVal1);
        } else {
            console.log(val1);
        }
        console.log(val2);
    });
}

testFunc();

Expected behavior:

This code should compile properly without issues. It compiles fine on 4.1.2 and also compiled fine on previous releases going all the way back to at least 3.8.

Actual behavior:

I get this output from tsc with the command-line yarn run tsc test.ts. There is no tsconfig.json file in the folder at the time.

test.ts:27:47 - error TS2339: Property 'reverse' does not exist on type 'string | any[]'.
  Property 'reverse' does not exist on type 'string'.

27             const reversedVal1 = val1.slice().reverse();
                                                 ~~~~~~~


Found 1 error.

Playground Link: https://www.typescriptlang.org/play?ts=4.2.0-dev.20201211#code/JYOwLgpgTgZghgYwgAgCoQM5gMJwxAHlWQgA9IQATDZLKUAc2QB9kQBXAWwCNoA+ZAG8AUMjHIoEOJQD2IADYBPZADc48gIwAuNC2QAlKbIWKAglChxFRPgG5R4ydLlLV6gEw7Dzk+cvXUO2EAX2FhUEhYRBQAWXZ5MGBcfAAxYHJ2SRshBzEEPEwdVABtAF17UOEYdhAERLladm4AETgwOBSahAAKAEoizBwCgjpGPQ4efjKc8QkIMEyQZGLc2aE3TR0AIjgtgBoNz2Wd-eQt7lOthC3S5GC91dnBDe1kdwO1eSPijQP35AAzLd7o9xM9Pq9iicDlsAF43D4eHRQ0iXRSXeHAh5rMEvZEAVgOGgADKVEV9kSSicTidSaVjVuUQmFqrV6ktKG0Ol0bN0ME1OrUdH1kABeAQlUr9ZBxBJJAppDJZQIzRzzRbrfL4DA6fncQU9Xp3Cosrrs5CQLAGkUiWYIORYZAwdILSRi5Cc9oGoiDZKEUYgJisCa8KB8Ph8pqtL1dXr2WbOpUQAB0WswyZgMigAFFEAALbrdcHqX6HO5G8WqnHAGDIbp+KzJ4AYBuKboQ3pG204tb2kCOyQqaD4SgANRL7ohyYw8mASD6ycHw4gfXjPbtDpk8hT8hkDG6S6gI-HmjjoLEwRI8nwVfXyD7GC3O737ZLZ-XoXXD6fyd3+8+7jvuIwRnpUlpgNacZAA

Related Issues:

According to #40463 and #41808, an issue with Array.isArray has already been fixed and is supposedly in 4.1.3.

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Dec 16, 2020
@typescript-bot typescript-bot added the Has Repro This issue has compiler-backed repros: https://aka.ms/ts-repros label Dec 16, 2020
@typescript-bot
Copy link
Collaborator

typescript-bot commented Dec 17, 2020

👋 Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of the repro in this issue running against the nightly TypeScript. If something changes, I will post a new comment.


Issue body code block by @mwgamble

👍 Compiled

Historical Information

Issue body code block by @mwgamble

Version Reproduction Outputs
4.1.2

❌ Failed: -

  • Property 'reverse' does not exist on type 'string | any[]'. Property 'reverse' does not exist on type 'string'.

3.7.5, 3.8.2, 3.9.2, 4.0.2, Nightly

👍 Compiled

@mwgamble
Copy link
Author

Not to sound rude, but Repro Bot is incorrect. Unless there's something really weird about my setup, this issue is not occurring on 4.1.2. It started on 4.1.3.

This is the playground link for 4.1.2, where there are most certainly no errors:

https://www.typescriptlang.org/play?ts=4.1.2#code/JYOwLgpgTgZghgYwgAgCoQM5gMJwxAHlWQgA9IQATDZLKUAc2QB9kQBXAWwCNoA+ZAG8AUMjHIoEOJQD2IADYBPZADc48gIwAuNC2QAlKbIWKAglChxFRPgG5R4ydLlLV6gEw7Dzk+cvXUO2EAX2FhUEhYRBQAWXZ5MGBcfAAxYHJ2SRshBzEEPEwdVABtAF17UOEYdhAERLladm4AETgwOBSahAAKAEoizBwCgjpGPQ4efjKc8QkIMEyQZGLc2aE3TR0AIjgtgBoNz2Wd-eQt7lOthC3S5GC91dnBDe1kdwO1eSPijQP35AAzLd7o9xM9Pq9iicDlsAF43D4eHRQ0iXRSXeHAh5rMEvZEAVgOGgADKVEV9kSSicTidSaVjVuUQmFqrV6ktKG0Ol0bN0ME1OrUdH1kABeAQlUr9ZBxBJJAppDJZQIzRzzRbrfL4DA6fncQU9Xp3Cosrrs5CQLAGkUiWYIORYZAwdILSRi5Cc9oGoiDZKEUYgJisCa8KB8Ph8pqtL1dXr2WbOpUQAB0WswyZgMigAFFEAALbrdcHqX6HO5G8WqnHAGDIbp+KzJ4AYBuKboQ3pG204tb2kCOyQqaD4SgANRL7ohyYw8mASD6ycHw4gfXjPbtDpk8hT8hkDG6S6gI-HmjjoLEwRI8nwVfXyD7GC3O737ZLZ-XoXXD6fyd3+8+7jvuIwRnpUlpgNacZAA

This is the playground link for 4.1.3, where there is an error:

https://www.typescriptlang.org/play?ts=4.1.3#code/JYOwLgpgTgZghgYwgAgCoQM5gMJwxAHlWQgA9IQATDZLKUAc2QB9kQBXAWwCNoA+ZAG8AUMjHIoEOJQD2IADYBPZADc48gIwAuNC2QAlKbIWKAglChxFRPgG5R4ydLlLV6gEw7Dzk+cvXUO2EAX2FhUEhYRBQAWXZ5MGBcfAAxYHJ2SRshBzEEPEwdVABtAF17UOEYdhAERLladm4AETgwOBSahAAKAEoizBwCgjpGPQ4efjKc8QkIMEyQZGLc2aE3TR0AIjgtgBoNz2Wd-eQt7lOthC3S5GC91dnBDe1kdwO1eSPijQP35AAzLd7o9xM9Pq9iicDlsAF43D4eHRQ0iXRSXeHAh5rMEvZEAVgOGgADKVEV9kSSicTidSaVjVuUQmFqrV6ktKG0Ol0bN0ME1OrUdH1kABeAQlUr9ZBxBJJAppDJZQIzRzzRbrfL4DA6fncQU9Xp3Cosrrs5CQLAGkUiWYIORYZAwdILSRi5Cc9oGoiDZKEUYgJisCa8KB8Ph8pqtL1dXr2WbOpUQAB0WswyZgMigAFFEAALbrdcHqX6HO5G8WqnHAGDIbp+KzJ4AYBuKboQ3pG204tb2kCOyQqaD4SgANRL7ohyYw8mASD6ycHw4gfXjPbtDpk8hT8hkDG6S6gI-HmjjoLEwRI8nwVfXyD7GC3O737ZLZ-XoXXD6fyd3+8+7jvuIwRnpUlpgNacZAA

@orta
Copy link
Contributor

orta commented Dec 18, 2020

Interesting, wonder what's up with the bot then - it should be the same underlaying code as the playground. Perhaps the repro bot has a default setting set which causes it to act differently.

Confirmed that the error occurs on master in a test case too. It can be fixed by reverting this:

-                // If the candidate type is a subtype of the target type, narrow to the candidate type,
-                // if the target type is a subtype of the candidate type, narrow to the target type,
-                // otherwise, narrow to an intersection of the two types.
-                return isTypeSubtypeOf(candidate, type) ? candidate : isTypeSubtypeOf(type, candidate) ? type : getIntersectionType([type, candidate]);
+                 // If the candidate type is a subtype of the target type, narrow to the candidate type.^M
+                 // Otherwise, if the target type is assignable to the candidate type, keep the target type.^M
+                 // Otherwise, if the candidate type is assignable to the target type, narrow to the candidate^M
+                 // type. Otherwise, the types are completely unrelated, so narrow to an intersection of the^M
+                 // two types.^M
+                 return isTypeSubtypeOf(candidate, type) ? candidate :
+                     isTypeAssignableTo(type, candidate) ? type :
+                     isTypeAssignableTo(candidate, type) ? candidate :
+                     getIntersectionType([type, candidate]);

Will remove the error - @weswigham, do you have a good argument for keeping it around?

@orta orta added Bug A bug in TypeScript and removed Needs Investigation This issue needs a team member to investigate its status. labels Dec 18, 2020
angeloashmore added a commit to WalltoWall/calico that referenced this issue Dec 23, 2020
Gerrit0 added a commit to TypeStrong/typedoc that referenced this issue Dec 28, 2020
@mwgamble
Copy link
Author

Is there an update on this? I can see that some related PRs appear to have been merged.

@orta
Copy link
Contributor

orta commented May 12, 2021

The changes should have all been reverted I believe, good reminder to close this out

@orta orta closed this as completed May 12, 2021
@lorenzodallavecchia
Copy link

@orta is the fix in 4.3 already?
Testing in v4.3.0-beta still shows some problems.

If you look at the playground @mwgamble at line 27 the val1 variable is refined as any[] and so it appears to work. However, in typescript@4.1.2 it was correctly inferred as (string|number)[].

Also, see this playground of mine.

  • on typescript@4.1.2
    This is the last version where everything worked.
  • on typescript@4.3.0-beta
    The inferred type for elem at line 3 is any and is not even reported by noImplicitAny!
    Also note how the infeered type of the false branch of the guard is not refined, causing the error at line 5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Has Repro This issue has compiler-backed repros: https://aka.ms/ts-repros
Projects
None yet
Development

No branches or pull requests

5 participants