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
keyof
now returns all known keys of a types includingstring
,number
andsymbol
keys. and as such, the constraint onkeyof E
is 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
: