-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Closed
Labels
QuestionAn issue which isn't directly actionable in codeAn issue which isn't directly actionable in code
Description
TypeScript Version: 2.8.3 and 2.9.1 (I think. The actual version in playground)
Code
The next code works as expected.
interface I {
property: number;
method1(): void;
method2(a: string): number;
}
declare const ob: I;
declare function foo<T, K extends keyof T>(ob: T, key: K): T[K];
const f1 = foo(ob, 'property'); // number
const f2 = foo(ob, 'method1'); // () => void
const f3 = foo(ob, 'method2'); // (a: string) => number
// f1(); OK, not a function
f2();
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
.
type FunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T];
declare function bar<T, K extends FunctionPropertyNames<T>>(ob: T, key: K): T[K];
// const f4 = bar(ob, 'property'); OK, 'property' is not allowed
const f5 = bar(ob, 'method1'); // () => void | (a: string) => number
const f6 = bar(ob, 'method2'); // () => void | (a: string) => number
// ERROR! Both are of type '() => void | (a: string) => number'
f5();
f6('a string');
// Type assertion
const f7 = bar(ob, 'method1' as 'method1'); // () => void
const f8 = bar(ob, 'method2' as 'method2'); // (a: string) => number
// OK again
f7();
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)
aleclarson and antoinebrault
Metadata
Metadata
Assignees
Labels
QuestionAn issue which isn't directly actionable in codeAn issue which isn't directly actionable in code