You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Parameter of type 'K extends FunctionPropertyNames<T>' is always a union type and not restricted to the string literal passed to function #25215
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.
Another workaround is to simply change FunctionPropertyNames<T> to
typeFunctionPropertyNames<T>={[KinkeyofT]: T[K]extendsFunction ? K : never}[keyofT]&string;
The intersection with string makes it clear to the compiler that the type is a subtype of string which in turn makes it clear that you want to preserve literal types during type inference.
Reacted by Daniel Contreras, Alec Larson, Nicholas Montaño, Xin, Sergey and Tomáš Dvořák
Anders Hejlsberg (@ahejlsberg) Could you explain why the checker doesn't do that without the & string? I am not an expert on this matter but I can't figure out why.
Activity
RyanCavanaugh commentedon Aug 17, 2018
Two possible workarounds and you can pick your favorite
or
ahejlsberg commentedon Aug 17, 2018
Another workaround is to simply change
FunctionPropertyNames<T>toThe intersection with
stringmakes it clear to the compiler that the type is a subtype ofstringwhich in turn makes it clear that you want to preserve literal types during type inference.InExtremaRes commentedon Aug 18, 2018
Thank you very much for the answers.
Anders Hejlsberg (@ahejlsberg) Could you explain why the checker doesn't do that without the
& string? I am not an expert on this matter but I can't figure out why.aleclarson commentedon Sep 13, 2018
I'm also curious why
& stringis necessary.