TypeScript Version: Version 2.9.0-dev.20180426
Search Terms: keyof not assignable string
Code
//Just a minimal example, not what I am actually doing
function isKey<E> (str : string) : str is keyof E {
return true;
}
Expected behavior:
Should compile fine. The body of the type guard may actually correctly assert that str is, indeed, keyof E
Works fine on TypeScript 2.8.3
Actual behavior:
error TS2677: A type predicate's type must be assignable to its parameter's type.
Type 'keyof E' is not assignable to type 'string'.
Type 'string | number | symbol' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'
Playground Link: Works on the playground
Related Issues:
This is a breaking change in TS 2.9 (documentation should come soon) introduced by https://github.com/Microsoft/TypeScript/pull/23592. With https://github.com/Microsoft/TypeScript/pull/23592 keyof now returns all known keys of a types including string, number and symbol keys. and as such, the constraint on keyof E is now string | number | symbol.
If you are interested in getting only the string portions of the keys, use Extract:
function isKey<E>(str: string): str is Extract<keyof E, string> {
return true;
}
if your function is meant to handle all property names, including symbols, then consider widening the declaration of str:
function isKey<E> (str : string | number | symbol) : str is keyof E {
return true;
}
Also, as a temporary measure you can use the new --keyofStringsOnly compiler option to revert to the old behavior.
Thanks for the swift response!
However, if I specifically mention that my type has only string keys like this:
interface A { [k: string]: any; }
type b = keyof A;
still, I get the type of b as string | number as seen in the IntelliSense on vs code:

Why is that so? Why is it not string only?
Typescript used: 3.9.3
Most helpful comment
This is a breaking change in TS 2.9 (documentation should come soon) introduced by https://github.com/Microsoft/TypeScript/pull/23592. With https://github.com/Microsoft/TypeScript/pull/23592
keyofnow returns all known keys of a types includingstring,numberandsymbolkeys. and as such, the constraint onkeyof Eis nowstring | number | symbol.If you are interested in getting only the string portions of the keys, use
Extract:if your function is meant to handle all property names, including symbols, then consider widening the declaration of
str: