Skip to content

Continuing #17110 - Given generic W extends { x: A } should be able to use keyof W['x'] to index w.x #33181

Description

@timhwang21

TypeScript Version: typescript@3.7.0-dev.20190831

Search Terms: tagged disjoint union generic

This issue stems from a question I asked on StackOverflow that Joe Calzaretta (@jcalz) generously researched for me. I adapted his example to be a closer parallel to the example given in #17110.

Code

interface A { a: string; }

interface W {
    x: A
}

function foo<W1 extends W>(w: W1, k: keyof W1['x']) {
  w.x[k]; // Type 'keyof W1["x"]' cannot be used to index type 'A'.

  const x: W1['x'] = w.x; // Okay
  x[k] // Okay
}

Expected behavior:

Same as #17110. However, unlike #17110, W['x'] is only A instead of A | B | undefined. The explanation given as to why #17110 was not a bug was:

The constraint of keyof W1["x"] is keyof (A | B), which simplifies to keyof A & keyof B, which is never (because there are no common properties).

However, here keyof W1['x'] is keyof A which is not never.

Actual behavior:

Same as #17110.

Playground Link: http://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgILIN7LgLmQZzClAHMBuZAXwChrRJZEUB1Ta5D5ADz1WpuowAriARhgAexDIYEiQB5mARmQQukEABN8yZgD4AFAHc8ygDTIA1nksQAnhJi6lAbQDkXNwF0AlGw5GAHRcLpZeFAD0EcgAKnYADihutg5Oyi4ARFwZXm7ICHAgIBJgyABGKEL4EJrIYBLIoJpqdQlJqG6BtBwIUoTcpq4e3sgAvMhBXJHRAPKWcHbs3KFeyFHIcwv8QA

Related Issues: #17110

Activity

  1. jack-williams commented on Sep 1, 2019

    @jack-williams
    Collaborator

    Property access and element access return the corresponding property type of the constraint, so w.x and w['x'] have type A, this is why the the access with k fails. Once you fall back to something concrete you can't later index with something generic.

    The access x[k] works because it uses the declared type which is a generic indexed access type which has been sufficiently deferred, therefore retaining its 'generic-ness'.

    I think the only approach that might solve this is to synthesise more indexed access types for property access expressions, perhaps under certain conditions such as being part of larger chain of property access where the outer keys are generic.

    Feels like a design limitation, but I'm not certain.

  2. sandersn commented on Sep 3, 2019

    @sandersn
    Member

    Under the current design, it is. I think we might have the machinery to cheaply switch over from w.x: A to w.x: W1['x'] at this point, but it sounds like a breaking change. To make it happen, we would need

    1. At least a prototype implementation.
    2. An idea of how breaky the change is, as measured by running on the user/RWC/docker/DefinitelyTyped test suites.
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

    Experimentation NeededSomeone needs to try this out to see what happensSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions