Description
openedon Feb 7, 2018
TypeScript Version: 2.8.0-dev.20180204
Search Terms: in
operator type guard generic assert
Code
function f<K extends string, T extends object>(key: K, genericObj: T, concreteObj: {foo: string}) {
if ('a' in concreteObj) {
concreteObj.a // error, Property 'a' does not exist on type 'never'.
}
if ('a' in genericObj) {
genericObj.a // error, Property 'a' does not exist on type 'T'.
}
if (key in concreteObj) {
concreteObj[key]; // error, Type 'K' cannot be used to index type '{ foo: string; }'
}
if (key in genericObj) {
genericObj[key] // error, Type 'K' cannot be used to index type 'T'.
}
}
Actual behavior:
The compiler does not recognize that the objects have relevant keys even after checking for the existence of the key with the in
operator. According to a comment by @sandersn, the in
type guard (as implemented in #15256) narrows by eliminating members from a union; it does not assert that a key exists.
Desired behavior:
The compiler would assert that each object had a property with the relevant key, after having checked for the existence of the key with the in
operator. Note that one possible implementation of an asserting type guard would look like
function inOperator<K extends string, T extends object>(k: K, o: T): o is T & Record<K, unknown> {
return k in o;
}
but this does not behave exactly as desired, possibly due to the bug in #18538: (not sure if #18538 was officially fixed, but it's not erroring anymore)
function g<K extends string, T extends object>(key: K, genericObj: T, concreteObj: { foo: string }) {
if (inOperator('a', concreteObj)) {
concreteObj.a // okay
}
if (inOperator('a', genericObj)) {
genericObj.a // okay
}
if (inOperator(key, concreteObj)) {
concreteObj[key]; // okay
}
if (inOperator(key, genericObj)) {
genericObj[key] // okay
}
}
If a fix for #18538 appears and makes the g()
function compile without error, great. Otherwise, maybe the property assertion for in
could happen some other way. Not sure.
Playground Link: Here
Related Issues:
#10485, Treat in
operator as type guard
#15256, Add type guard for in
keyword
#18538, Error when mixing keyof
and intersection type and type variable (fixed?)
(EDIT: #18538 seems to be fixed)
(EDIT: change any
to unknown
)