TypeScript Version: 2.8.3 and 2.9.1 (I think. The actual version in playground)
Code
The next code works as expected.
interfaceI{property: number;method1(): void;method2(a: string): number;}declareconstob: I;declarefunctionfoo<T,KextendskeyofT>(ob: T,key: K): T[K];constf1=foo(ob,'property');// numberconstf2=foo(ob,'method1');// () => voidconstf3=foo(ob,'method2');// (a: string) => number// f1(); OK, not a functionf2();f3('a string');But I want to restrict the key parameter in foo to just functions.
Since #21316, and as an example on that PR, we can use something like FunctionPropertyNames.
typeFunctionPropertyNames<T>={[KinkeyofT]: T[K]extendsFunction ? K : never}[keyofT];declarefunctionbar<T,KextendsFunctionPropertyNames<T>>(ob: T,key: K): T[K];// const f4 = bar(ob, 'property'); OK, 'property' is not allowed constf5=bar(ob,'method1');// () => void | (a: string) => numberconstf6=bar(ob,'method2');// () => void | (a: string) => number// ERROR! Both are of type '() => void | (a: string) => number'f5();f6('a string');// Type assertionconstf7=bar(ob,'method1'as'method1');// () => voidconstf8=bar(ob,'method2'as'method2');// (a: string) => number// OK againf7();f8('a string');Expected behavior:
f5 and f6 inferred to () => void and (a: string) => number, respectively, without need a type assertion (pretty much as the first snippet).
Actual behavior:
f5 and f6 are both inferred to () => void | (a: string) => number, which is very odd since I'm passing a literal string.
Playground link
Playground link
Related Issues:
Maybe #24080 (but that seems related to the keyof T ~ string | number | symbol issue and my example fails with TS 2.8)
TypeScript Version: 2.8.3 and 2.9.1 (I think. The actual version in playground)
Code
The next code works as expected.
But I want to restrict the
keyparameter infooto just functions.Since #21316, and as an example on that PR, we can use something like
FunctionPropertyNames.Expected behavior:
f5andf6inferred to() => voidand(a: string) => number, respectively, without need a type assertion (pretty much as the first snippet).Actual behavior:
f5andf6are both inferred to() => void | (a: string) => number, which is very odd since I'm passing a literal string.Playground link
Playground link
Related Issues:
Maybe #24080 (but that seems related to the
keyof T~string | number | symbolissue and my example fails with TS 2.8)