Typescript: `keyof` operator does not impose constraints on generic parameter

Created on 3 Nov 2016  路  4Comments  路  Source: microsoft/TypeScript

TypeScript Version: nightly(2.1.0-dev.20161103)

Code

function prop<S, K extends keyof S>(name: K): (s: S) => any {
  return s => s[name]
}

const getProp = prop('test')
const a = getProp({test: 123})

Expected behavior:

Code compiles, getProp is typed as (v: {test: {}}) => any

Actual behavior:

Argument of type "test" is not assignable to parameter of type 'never'

I don't know whether it is an intended behavior. As a comparison, flow seems to, well, cough partly, cough, support it.

https://flowtype.org/try/#0PQKgBAAgZgNg9gdzCYAoVUCuA7AxgFwEs5swAHAJzjIB4BlALjAHkAjAKwFMCAaMAaSYASfpwCeAZ3oA+aQApsAQwC2nJvwCUTORKZ0NYALzSwi7GLABvVGDAVO+TBVI69B42AkBtJaoC6qAC+6LgkEvhgAOYOAApUZEbk8XIA5Pic4SkaqKHY4aaJ0fhx1HKW6eFMAIwATADMgdlAA

Most helpful comment

My brain hurts from reading that definition :(

All 4 comments

The problem is that S isn't inferred as part of the call to the outermost arrow function, so you end up with {} as the type of S, and the empty union as the type of keyof S (because keyof {} is never). Thus, K has an effective constraint of never which "test" isn't compatible with.

As I pointed out with @ahejlsberg a few weeks ago, you really want a to _invert_ the contraint somehow:

function prop<K extends string>(name: K): <S extends { [K]: any }>(s: S) => S[K] {
    return s => s[name];
}

Here, { [K]: any } means that for whatever K is, there is an object type with property names unioned within K.

I think I can mark this feature as a sub feature of https://github.com/Microsoft/TypeScript/issues/5683?

Works like a charm after #11929, fantastic!

function prop<K extends string>(k: K): <V>(v: {[k in K]: V} & {[k: string]: any}) => V {
    return v => v[k]
}

var testProp = prop('test')

var num = testProp({test: 123, additional: 'additional'})

My brain hurts from reading that definition :(

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dlaberge picture dlaberge  路  3Comments

siddjain picture siddjain  路  3Comments

remojansen picture remojansen  路  3Comments

Antony-Jones picture Antony-Jones  路  3Comments

bgrieder picture bgrieder  路  3Comments