**TypeScript Version:** 2.8.0-dev.20180204 **Search Terms:** `in` operator type guard generic assert **Code** ```ts 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](https://github.com/Microsoft/TypeScript/issues/18538#issuecomment-363841353) 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 ```ts function inOperator<K extends string, T extends object>(k: K, o: T): o is T & Record<K, unknown> { return k in o; } ``` <strike>but this does not behave exactly as desired, possibly due to the bug in #18538: </strike> (not sure if #18538 was officially fixed, but it's not erroring anymore) ```ts 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 } } ``` <strike>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.</strike> **Playground Link:** [Here](https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABMAPAaUQUwB5U2AEwGdEioAnGMAcwBpEAVLXfYxOAIwCtNoA+ABQBrTAE8AXIjT1q+TJQgB5bpIb0ICCOUx5lXSQG9kcOJLKUaiAL4BKRAYCwAKESIYwRAIDkAQy9ukDUhtXW47RxdXRCCtHUw9ADofRAB6FKxycjhyegAFLIAHeShRRF9-AjhMEjA4KGYYMnYkEqKysEwAN3kvBOdXK363D28-AMRZDoU9cKHXSfkYJW4k1PT5LJzEfLgi8hKyscrqxFr6nEb6hERWzDKGXqHByPdPEVKqaM0Q+LD7Oa+wTiegA2u8ALoAbjWGU29AYojaXjQ-ggPjAZ0QHDuICImAINzgAQIOBuiLuXiMwBMZgoVGo0KsXieQ1ewjE4wW0z+ESiEzk3K4YLE4JhG2y8PJZRR0XRmOxiFx+MJxNJt3uj0iz2ezlAkFg1yoij2Pig2XQzDwhBI5np8MtrBInB4-GEkmk7FUNkkRMajEQADJEAAlXjZAjoejgIS1ADuYD4-0iIRA5CQQnGcEhzh1Tj10HgSGoFpwVrYtpo9tLjvY3F4UEE73dMgFSz0qnU32BKnsxlMpDpllsSdcbKNJrN5FGXk7QNCXBss0irhiP0SyTS7CEPlELJeI3H8lN2WnLambbCS75XIvXFWm7g293WtZB7AxqPk-ZolnsXni5HKJV27IUIWhB8nz3Uc3w-chjynd4z0WZYFyvKIbxQ4VRFFCCdz3KwgA) **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`)