Skip to content

Given generic W extends { x: A | B | undefined } should be able to use keyof W['x'] to index w.x #17110

Closed
@studds

Description

@studds

TypeScript Version: 2.4.0 / nightly (2.5.0-dev.201xxxxx)

2.4.1 (playground)

Code

// A *self-contained* demonstration of the problem follows...

interface A { a: string; }

interface B {  b: string; }

interface W {
    x: A | B | undefined;
}

function fn2<W1 extends W>(w: W1, k: keyof W1['x']) {
    // issue 1: incorrect error: Type 'keyof W1["x"]' cannot be used to index type 'Partial<A> | Partial<B>'.
    // also correctly reports error: Object is possibly 'undefined'.
    w.x[k] = 'string';

    // this is fine, with the explicit type
    const x: W1['x'] = w.x;
    // issue 2: Should complain that w.x might be undefined
    x[k] = 'string';
}

// Inside the generic function, W1['x'] is unnecessarily and prematurely resolved to `A | B | undefined`, 
// causing the error to be incorrectly reported.
// The final type of W1['x'] and keyof W1['x'] should only be resolved when the function is called.
// This in fact works correctly already. 

// correctly infers type of param k, errors: Argument of type '"a"' is not assignable to parameter of type '"b"'.
fn2({ x: { b: '' } }, 'a');

// no error
fn2({ x: {  b: '' } }, 'b');

// k is correctly resolved to never: Argument of type '"a"' is not assignable to parameter of type 'never'.
let ambiguous: W = <W>{};
fn2(ambiguous, 'a');
fn2({ x: undefined }, 'a');

Expected behavior:

  1. Given a generic W extends { x: A | B | undefined } should be able to use keyof W['x'] to index w.x
  2. Should complain that w.x could be undefined after assigning to explicitly typed variable W['x']

Actual behavior:

  1. Errors unless you create a local variable with explicit type W['x']: const x: W['x'] = w.x;
  2. Does not complain that x could be undefined after assigning to explicitly typed variable W['x']

Metadata

Metadata

Assignees

Labels

Working as IntendedThe behavior described is the intended behavior; this is not a bug

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions