Skip to content

Type narrowing in checked JS in module scope doesn't work #31667

@TedDriggs

Description

@TedDriggs

TypeScript Version: 3.4.5

Search Terms: JS, Narrowing, Module Scope

Code

// In file1.d.ts ======================
declare class Example1 {
    private constructor();
    public has(value: string): boolean;
}

interface Example2 {
    id: string;
    doSomething(key: string): void;
}

interface Example2Static {
    readonly prototype: Example2;
    (id: string): Example2;
}

declare const Example2: Example2Static;

declare const Reader: {
    get: (name: string) => string | boolean | null | Example1 | Example2;
}

// In file2.js ===================
const inModuleScope = Reader.get('approved');

// In JS with allowJs and checkJs on, this DOES NOT narrow
if (inModuleScope instanceof Example1) {
    inModuleScope.has('blah');
} else if (inModuleScope instanceof Example2) {
    inModuleScope.doSomething('hi');
}

(function () {
    // In JS with allowJS and checkJS on, `val` below DOES narrow
    // It's even possible to narrow `inModuleScope`
    const val = Reader.get('approved');
    if (val instanceof Example1) {
        val.has('blah');
    } else if (val instanceof Example2) {
        val.doSomething('hi');
    }
})();

Expected behavior:
The inModuleScope type guards should narrow inModuleScope so the two calls are valid inside the if and else-if blocks.

Actual behavior:
inModuleScope won't narrow unless inside a function. However, it will narrow in TS.

Playground Link: Link, but this won't demonstrate the bug because checkJS is needed

Related Issues: None found

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptDomain: JavaScriptThe issue relates to JavaScript specifically

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions