Skip to content

T[keyof T] type constraint lost in function body #12991

Closed

Description

TypeScript Version: 2.1.4 / nightly (2.2.0-dev.20161216)

function fn<T extends {[P in K]: string}, K extends keyof T>(obj: T, key: K) {
  const val: string = obj[key];  // error TS2322: Type 'T[K]' is not assignable to type 'string'
}

fn({ str: "s", num: 1 }, "str"); // OK
fn({ str: "s", num: 1 }, "num"); // error TS2345: Argument of type '{ str: string; num: number; }' is not assignable to parameter of type '{ num: string; }

Expected behavior:

Given the constraints, I would expect obj[key] in this case to be of type string.

Actual behavior:

The type of obj[key] is the less specific T[K].

Considering the error at the second call site (which is expected), it seems that the type checking done there is complete and working. However, that same type info is not carried through into the function body itself.

Activity

  1. ajafff commented on Jan 23, 2018

    @ajafff
    Contributor

    I witnessed the same bug. I noticed that this problem only exists if both obj and key are TypeParameters.

    // typescript@2.7.0-rc with --strictNullChecks
    declare function foo(p: string): void;
    
    interface I {
        foo?: string;
        bar?: string;
    }
    
    function working1<T extends I>(o: T, k: keyof I) {
        foo(o[k]); // getting expected type error here, because type is `string | undefined`
    }
    
    function working2<K extends keyof I>(o: I, k: K) {
        foo(o[k]); // getting expected type error here, because type is `string | undefined`
    }
    
    function notWorking<T extends I, K extends keyof T>(o: T, k: K) {
        foo(o[k]); // expected type error, but got none
    }

    Inside notWorking o[k] is treated as any. At least that's what checker.getApparentType(checker.getTypeAtLocation(node)) tells me.

  2. mhegazy commented on Feb 1, 2018

    @mhegazy
    Contributor

    These should be working now as expected.

  3. locked and limited conversation to collaborators on Jul 3, 2018
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

    BugA bug in TypeScriptFixedA PR has been merged for this issue

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions