microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.03k stars 12.49k forks source link

type.isLiteral() returns false for boolean literals #26075

Open dsherret opened 6 years ago

dsherret commented 6 years ago

TypeScript Version: 3.1.0-dev.20180728 (new in 3.0.1)

Search Terms: isLiteral()

Code

  1. Create a boolean literal in the compiler api.
  2. Call isLiteral() on it.

Change seems to be done here:

https://github.com/Microsoft/TypeScript/commit/e46d214fceb72cc76145779543bf871ce9ff66b0#diff-233e1126c0abc811c4098757f9e4516eR428

Expected behavior: true for a boolean literal type (true or false)

Actual behavior: false

I have a few tests for assumptions about the compiler api in ts-simple-ast and this one started failing. Maybe it's not a bug, but I thought I would log it anyway to find out why this behaviour changed.

Is it because it doesn't have the Unit flag while string and number literals do? For what it's worth, in checker.ts it will internally return true for boolean literals in isLiteralType.

ajafff commented 6 years ago

This is because a boolean literal type is actually not represented by a LiteralType but really is a IntrinsicType. If you understand .isLiteral() as a type guard (is this an instance of LiteralType) instead of just a method that tells you if it originated in a literal, it kind of makes sense.

DanielRosenwasser commented 6 years ago

Let's chat whether we should fix this @weswigham.

dsherret commented 6 years ago

@ajafff oh yeah, good point! These methods on Type are for type guarding after all.

Another point: the common LiteralType interface's value property was previously and currently has type string | number rather than string | number | boolean.

interface LiteralType extends Type {
    value: string | number;
    // ...
}

So isLiteral()'s new behaviour seems like a fix for the current design.

That said, as an API user it does seem a bit unexpected that boolean literal types aren't included with LiteralType, but I don't have a use case where it would matter.

ajafff commented 6 years ago

That said, as an API user it does seem a bit unexpected that boolean literal types aren't included with LiteralType, but I don't have a use case where it would matter.

I need it quite often and it's annoying, see #22269

RyanCavanaugh commented 6 years ago

Consensus was that this function should return true for booleans as expected

Kingwl commented 6 years ago

is that mean we want boolean to be a literal?(booleanLiteral extends Literal and has a boolean 'value' prop)

marijnh commented 5 years ago

I just ran into this too (needing to use undocumented internals to get at the value of a boolean literal type). So to second @Kingwl 's question—is the intent to add a BooleanLiteralType interface to the public API? Anything someone undertaking such a change should be careful about?