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

true extends false #28654

Closed
AnyhowStep opened this issue Nov 23, 2018 · 6 comments
Closed

true extends false #28654

AnyhowStep opened this issue Nov 23, 2018 · 6 comments
Assignees
Labels
Bug A bug in TypeScript Domain: Indexed Access Types The issue relates to accessing subtypes via index access Fixed A PR has been merged for this issue

Comments

@AnyhowStep
Copy link
Contributor

AnyhowStep commented Nov 23, 2018

TypeScript Version: 3.2.0-dev.20181117

EDIT: I just tested with TS 3.2.0-rc and it has this bug

Search Terms: true extends false

Code

I feel like I'm losing my mind here. Or maybe I'm tired because it's 3.34am. Maybe I need to take a break. Am I missing something obvious?

//OK
//Expected: "n"
//Actual: "n"
type no = true extends false ? "y" : "n";

type G<DataT extends { b : boolean }> = (
    true extends DataT["b"]?
    ["Actual", "true extends", DataT["b"]] :
    "Expected"
)

//Wat?
//Expected: "Expected"
//Actual: ["Actual", "true extends", false]
type g = G<{ b : false }>;

Expected behavior:

g to be of type "Expected".

Intuitively,

  1. DataT is of type { b : false }
  2. DataT["b"] is of type false
  3. true extends false should be... false

Actual behavior:

g is of type ["Actual", "true extends", false]

Playground Link: Here


EDIT: I just tested and this is not a problem in TS 3.0.1

I'm not crazy, phew.

@AnyhowStep
Copy link
Contributor Author

AnyhowStep commented Nov 23, 2018

This has no problems in either TS 3.2 or TS 3.0.1

type G<B extends boolean> = (
    true extends B?
    ["Actual", "true extends", B] :
    "Expected"
)

//OK
//Expected: "Expected"
//Actual: "Expected"
type g = G<false>;

@jack-williams
Copy link
Collaborator

I think this is happening because of #27470

In G the constraint of DataT is being pulled down in the access expression DataT["b"]. So it is not that true extends false, rather it is eagerly using the base constraint in DataT so you get true extends boolean. This is not covered by the fix #27490 because "b" is not a generic type. You can see the correct behaviour if you defer the check using a parameter.

type G2<DataT extends { b : boolean }, B extends keyof DataT> = (
    true extends DataT[B]?
    ["Actual", "true extends", DataT[B]] :
    "Expected"
)
// g2: "Expected"
type g2 = G2<{ b: false }, "b">;

or even doing:

type G2<DataT extends { b : boolean }, B extends "b"> = (
    true extends DataT[B]?
    ["Actual", "true extends", DataT[B]] :
    "Expected"
)
// g2: "Expected"
type g2 = G2<{ b: false }, "b">;

@AnyhowStep
Copy link
Contributor Author

AnyhowStep commented Nov 23, 2018

Yikes. I hope this is fixed. This breaks a lot of my code that was working in 3.0.1.

Using your workaround would make the type declarations even more verbose and complex =(


Thank you for looking into it! I had this gnawing at me even as I tried to sleep.

I guess I'll hold off on upgrading TS for now :x

@weswigham weswigham added Bug A bug in TypeScript Domain: Indexed Access Types The issue relates to accessing subtypes via index access labels Nov 26, 2018
@Jessidhia
Copy link

This might be related to some problems I found while working on the React types; proving that 'x' extends keyof T is not sufficient to let you index T with 'x'.

@ahejlsberg
Copy link
Member

Simplified repro with expected outcomes:

type Foo<T extends { b: boolean }> = true extends T["b"] ? "yes" : "no";

type T0 = Foo<{ b: never }>     // "no"
type T1 = Foo<{ b: false }>;    // "no"
type T2 = Foo<{ b: true }>;     // "yes"
type T3 = Foo<{ b: boolean }>;  // "yes"

Currently Foo is eagerly evaluated to "yes" so every outcome is "yes".

@ahejlsberg ahejlsberg assigned weswigham and unassigned weswigham Nov 28, 2018
@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label Nov 29, 2018
@DanielRosenwasser DanielRosenwasser added this to the TypeScript 3.3.0 milestone Nov 29, 2018
@AnyhowStep
Copy link
Contributor Author

Thank you for fixing this so quickly!

I just updated from 3.0.1 to 3.3.0-dev.20181129 and nothing broke!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: Indexed Access Types The issue relates to accessing subtypes via index access Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

6 participants