8000 Bad type checking for GenericType<boolean> vs GenericType<false> · Issue #33833 · microsoft/TypeScript · GitHub
[go: up one dir, main page]

Skip to content
Bad type checking for GenericType<boolean> vs GenericType<false> #33833
Closed
@thomcc

Description

@thomcc

TypeScript Version: 3.7.0-dev.20191006

Search Terms: covariance, subtype, inference, value type (... honestly I have no idea what the right term for "false when used as a type" is, it's... probably not this though).

Code:

class Grid<T> {
    constructor(width: number, height: number, defaultFill: T) { }
    // some function which either behaves as a fill or an in-place equivalent of map, for example
    fillWith(valueOrCallback: T | ((current: T, x: number, y: number, idx: number) => T)) {}
}

function takesBoolGrid(grid: Grid<boolean>) { }
// This causes a type error
takesBoolGrid(new Grid(16, 16, false));

// But this doesn't
let g = new Grid(16, 16, false);
takesBoolGrid(g);

Expected behavior: The code above should typecheck. Or, at the very least, both cases should fail, instead of assigning to an intermediate variable fixing the issue.

Actual behavior: I get an error like the following on the first call to takesBoolGrid:

Argument of type 'Grid<false>' is not assignable to parameter of type 'Grid<boolean>'.
  Types of property 'fillWith' are incompatible.
    Type '(valueOrCallback: false | ((current: false, x: number, y: number, idx: number) => false)) => void' is not assignable to type '(valueOrCallback: boolean | ((current: boolean, x: number, y: number, idx: number) => boolean)) => void'.
      Types of parameters 'valueOrCallback' and 'valueOrCallback' are incompatible.
        Type 'boolean | ((current: boolean, x: number, y: number, idx: number) => boolean)' is not assignable to type 'false | ((current: false, x: number, y: number, idx: number) => false)'.
          Type 'true' is not assignable to type 'false | ((current: false, x: number, y: number, idx: number) => false)'.(2345)

Playground Link: https://www.typescriptlang.org/play/?ts=3.7-Beta&ssl=1&ssc=1&pln=14&pc=1#code/MYGwhgzhAEDiBOBLAJgHgCoD5oG8CwAUNMdMAPYB2EALvAK7DVnwAUA7itQBYBc0FdALYAjAKbwANNC6jEAcy7U+AkeKnJRAMzB0Q1AGKIQIPugCUuaAF9CJaAHp70CGUGjomuhUaJK0NlyIwFzQstzi0GJcYABuojCQ0GAeRiDQzEkU0IgUALQADuDA7qIAjnSIMWAgohTU6ZrQgmD5UpoZogAeYIKForYkmqkA6ojcLFUgdKIA8vAAwtUgwmDAANam0AA+0CwswHTw8LVK0OhSncpCYpLQAJ5Xqrcol-zX4hYAvNjmFjg2BABhE83moviy1DAa3iACEyGQQAgUCw5EhkHwkWhhPCamAKJg-tZCI4zoEYMAdBB4kloNQ7vkSkdmIRIdCIHCEZiWBRRGw4GiWABGABsUhFbWqVLMZgA3IRiU4YXR6txEDBkGR4hQAOTUQg1epyaCffi8-nI8XQS3aEBSuUEVmwnFcuSywhAA

Related Issues: I looked, but sadly my search terms quickly brought me to a bunch of issues that assume more familiarity with tsc (and type system jargon, probably) than I have. (This is probably because the only terminology I have for describing this problem is, well, type system jargon that I only barely can say I understand).


Some notes that don't fit above which might help, possibly: this code used to work in like, typescript 2.something (I could probably find out which version it was on Monday if it would help).

I updated the code to the new typescript, and got this error, and assumed it was just typescript getting updated with some stricter behavior around variance. I complained online, and was asked to produce an example, and it turned out that the issue was weirder than I had though, as:

  1. It only errored if the fillWith function was present
  2. It didn't error if I assign the Grid to an intermediate variable.

Point 2 seems weird, so I decided to file a bug.

Note that (IMO fairly unsurprisingly) the expression takesBoolGrid(new Grid<boolean>(16, 16, false)) type checks fine, e.g. if the type is listed explicitly, no intermediate variable is needed. So I guess it's some kind of type inference thing too? Who knows... (hopefully someone here!)

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0