Skip to content

Equality operator with unknown does not narrow the type of the unknown #25172

Closed
@MadaraUchiha

Description

@MadaraUchiha

TypeScript Version: 3.0.0-dev.20180623

Search Terms: typescript unknown equality guard

Code

let x: unknown; // reproduces with const too
if (x === 5) {
    let y = x.toString(10);
}

Expected behavior:
x inside of the if block to be of type 5, y to get type of string, everyone happy.
Actual behavior:
x inside of the if block is still of type unknown, I get an error for x being of type unknown and therefore does not have a property toString.
Playground Link: N/A (dev build)

Related Issues: #24439

Activity

jcalz

jcalz commented on Jun 23, 2018

@jcalz
Contributor

Related to #9999 also?

MadaraUchiha

MadaraUchiha commented on Jun 23, 2018

@MadaraUchiha
Author

@jcalz Not exactly, that there is a feature request, unknown can be narrowed in other ways. The following is the result on the TypeScript version mentioned at the top of this issue:

let x: unknown; // unknown always considered initialized.
if (Array.isArray(x)) {
    x; // any[] (I would expect unknown[], but that's a different issue)
} else if (x instanceof Promise) {
    x; // Promise<any> (again, would expect Promise<unknown> but eh)
} else if (x === true) {
    x; // unknown, wat.
}
let y = String(x); // y: string, as expected
let z = Number(x); // z: number, as expected

So you see, the only real "wat" here is the direct equality comparison.

It's also worth noting that this behavior is consistent with any (That is, attempts to narrow any with equality are met with any as the narrowed type), but this is still rather unexpected behavior.

weswigham

weswigham commented on Jun 25, 2018

@weswigham
Member

@DanielRosenwasser === today doesn't narrow anything other than members from unions or primitives into literals today. unknown is neither a primitive nor a union, so this is expected under our current rules, just like how {} and any won't be narrowed by ===, either.

added
SuggestionAn idea for TypeScript
and removed
BugA bug in TypeScript
on Jun 25, 2018
removed this from the TypeScript 3.0 milestone on Jun 25, 2018
JacksonKearl

JacksonKearl commented on Jul 19, 2018

@JacksonKearl

This is especially helpful for narrowing unknown to a string enum

type Response = 'yes' | 'no' | 'idk';
let validate: (x: unknown) => Response = x => (x === 'yes' || x === 'no') ? x : 'idk'; // Err: type 'unknown' is not assignable to type '"idk"'
mhegazy

mhegazy commented on Jul 27, 2018

@mhegazy
Contributor

Similar requests in #10715, #25720, and #21732

17 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CommittedThe team has roadmapped this issueHelp WantedYou can do thisSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @jcalz@DanielRosenwasser@MadaraUchiha@weswigham@jack-williams

        Issue actions

          Equality operator with unknown does not narrow the type of the unknown · Issue #25172 · microsoft/TypeScript