From fe075f26a26a7813d622044a52505628265d6270 Mon Sep 17 00:00:00 2001
From: Anders Hejlsberg <andersh@microsoft.com>
Date: Fri, 2 Mar 2018 09:11:33 -0800
Subject: [PATCH 1/4] Transform 'keyof (A & B)' to 'keyof A | keyof B'

---
 src/compiler/checker.ts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 1931661bf5f7c..c476297bb68b0 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -7987,7 +7987,8 @@ namespace ts {
         }
 
         function getIndexType(type: Type): Type {
-            return maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive) ? getIndexTypeForGenericType(<InstantiableType | UnionOrIntersectionType>type) :
+            return type.flags & TypeFlags.Intersection ? getUnionType(map((<IntersectionType>type).types, t => getIndexType(t))) :
+                maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive) ? getIndexTypeForGenericType(<InstantiableType | UnionOrIntersectionType>type) :
                 getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(<MappedType>type) :
                 type === wildcardType ? wildcardType :
                 type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType :

From 4256be1591dcf140d38c0c6fe25e4a6a49bba869 Mon Sep 17 00:00:00 2001
From: Anders Hejlsberg <andersh@microsoft.com>
Date: Fri, 2 Mar 2018 09:24:59 -0800
Subject: [PATCH 2/4] Accept new baselines

---
 .../reference/indexedAccessRelation.types     |  4 +--
 .../reference/keyofAndIndexedAccess.types     | 28 +++++++++----------
 .../keyofAndIndexedAccessErrors.errors.txt    | 10 ++++---
 .../keyofAndIndexedAccessErrors.types         | 18 ++++++------
 4 files changed, 31 insertions(+), 29 deletions(-)

diff --git a/tests/baselines/reference/indexedAccessRelation.types b/tests/baselines/reference/indexedAccessRelation.types
index 2564a82702dd6..02884d8682a17 100644
--- a/tests/baselines/reference/indexedAccessRelation.types
+++ b/tests/baselines/reference/indexedAccessRelation.types
@@ -44,9 +44,9 @@ class Comp<T extends Foo, S> extends Component<S & State<T>>
 
         this.setState({ a: a });
 >this.setState({ a: a }) : void
->this.setState : <K extends keyof (S & State<T>)>(state: Pick<S & State<T>, K>) => void
+>this.setState : <K extends keyof S | "a">(state: Pick<S & State<T>, K>) => void
 >this : this
->setState : <K extends keyof (S & State<T>)>(state: Pick<S & State<T>, K>) => void
+>setState : <K extends keyof S | "a">(state: Pick<S & State<T>, K>) => void
 >{ a: a } : { a: T; }
 >a : T
 >a : T
diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types
index af441e865ff22..694abf7d10e56 100644
--- a/tests/baselines/reference/keyofAndIndexedAccess.types
+++ b/tests/baselines/reference/keyofAndIndexedAccess.types
@@ -888,20 +888,20 @@ function f60<T>(source: T, target: T) {
 }
 
 function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) {
->f70 : (func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) => void
->func : <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void
+>f70 : (func: <T, U>(k1: keyof (T | U), k2: keyof T | keyof U) => void) => void
+>func : <T, U>(k1: keyof (T | U), k2: keyof T | keyof U) => void
 >T : T
 >U : U
 >k1 : keyof (T | U)
 >T : T
 >U : U
->k2 : keyof (T & U)
+>k2 : keyof T | keyof U
 >T : T
 >U : U
 
     func<{ a: any, b: any }, { a: any, c: any }>('a', 'a');
 >func<{ a: any, b: any }, { a: any, c: any }>('a', 'a') : void
->func : <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void
+>func : <T, U>(k1: keyof (T | U), k2: keyof T | keyof U) => void
 >a : any
 >b : any
 >a : any
@@ -911,7 +911,7 @@ function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) {
 
     func<{ a: any, b: any }, { a: any, c: any }>('a', 'b');
 >func<{ a: any, b: any }, { a: any, c: any }>('a', 'b') : void
->func : <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void
+>func : <T, U>(k1: keyof (T | U), k2: keyof T | keyof U) => void
 >a : any
 >b : any
 >a : any
@@ -921,7 +921,7 @@ function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) {
 
     func<{ a: any, b: any }, { a: any, c: any }>('a', 'c');
 >func<{ a: any, b: any }, { a: any, c: any }>('a', 'c') : void
->func : <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void
+>func : <T, U>(k1: keyof (T | U), k2: keyof T | keyof U) => void
 >a : any
 >b : any
 >a : any
@@ -1034,8 +1034,8 @@ function f72(func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T &
 }
 
 function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]) {
->f73 : (func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]) => void
->func : <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]
+>f73 : (func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]) => void
+>func : <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]
 >T : T
 >U : U
 >K : K
@@ -1054,7 +1054,7 @@ function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[
     let a = func({ a: 1, b: "hello" }, { c: true }, 'a');  // number
 >a : number
 >func({ a: 1, b: "hello" }, { c: true }, 'a') : number
->func : <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]
+>func : <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]
 >{ a: 1, b: "hello" } : { a: number; b: string; }
 >a : number
 >1 : 1
@@ -1068,7 +1068,7 @@ function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[
     let b = func({ a: 1, b: "hello" }, { c: true }, 'b');  // string
 >b : string
 >func({ a: 1, b: "hello" }, { c: true }, 'b') : string
->func : <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]
+>func : <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]
 >{ a: 1, b: "hello" } : { a: number; b: string; }
 >a : number
 >1 : 1
@@ -1082,7 +1082,7 @@ function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[
     let c = func({ a: 1, b: "hello" }, { c: true }, 'c');  // boolean
 >c : boolean
 >func({ a: 1, b: "hello" }, { c: true }, 'c') : boolean
->func : <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]
+>func : <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]
 >{ a: 1, b: "hello" } : { a: number; b: string; }
 >a : number
 >1 : 1
@@ -1837,7 +1837,7 @@ declare class Component1<Data, Computed> {
 >Computed : Computed
 
     get<K extends keyof (Data & Computed)>(key: K): (Data & Computed)[K];
->get : <K extends keyof (Data & Computed)>(key: K) => (Data & Computed)[K]
+>get : <K extends keyof Data | keyof Computed>(key: K) => (Data & Computed)[K]
 >K : K
 >Data : Data
 >Computed : Computed
@@ -2035,9 +2035,9 @@ function onChangeGenericFunction<T>(handler: Handler<T & {preset: number}>) {
 
     handler.onChange('preset')
 >handler.onChange('preset') : void
->handler.onChange : (name: keyof (T & { preset: number; })) => void
+>handler.onChange : (name: keyof T | "preset") => void
 >handler : Handler<T & { preset: number; }>
->onChange : (name: keyof (T & { preset: number; })) => void
+>onChange : (name: keyof T | "preset") => void
 >'preset' : "preset"
 }
 
diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt b/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt
index 0b2da3f8e6107..49f44115e72fc 100644
--- a/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt
+++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt
@@ -22,11 +22,12 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(64,33): error
 tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(66,24): error TS2345: Argument of type '"size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'.
 tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(67,24): error TS2345: Argument of type '"name" | "size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'.
   Type '"size"' is not assignable to type '"name" | "width" | "height" | "visible"'.
-tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(72,5): error TS2536: Type 'keyof (T & U)' cannot be used to index type 'T | U'.
+tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(72,5): error TS2536: Type 'keyof T | keyof U' cannot be used to index type 'T | U'.
 tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(76,5): error TS2322: Type 'T | U' is not assignable to type 'T & U'.
   Type 'T' is not assignable to type 'T & U'.
     Type 'T' is not assignable to type 'U'.
-tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(77,5): error TS2322: Type 'keyof (T & U)' is not assignable to type 'keyof (T | U)'.
+tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(77,5): error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof (T | U)'.
+  Type 'keyof T' is not assignable to type 'keyof (T | U)'.
 tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(86,9): error TS2322: Type 'keyof T' is not assignable to type 'K'.
 tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(88,9): error TS2322: Type 'T[keyof T]' is not assignable to type 'T[K]'.
   Type 'keyof T' is not assignable to type 'K'.
@@ -161,7 +162,7 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(100,5): error
         o1[k1];
         o1[k2];   // Error
         ~~~~~~
-!!! error TS2536: Type 'keyof (T & U)' cannot be used to index type 'T | U'.
+!!! error TS2536: Type 'keyof T | keyof U' cannot be used to index type 'T | U'.
         o2[k1];
         o2[k2];
         o1 = o2;
@@ -172,7 +173,8 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(100,5): error
 !!! error TS2322:     Type 'T' is not assignable to type 'U'.
         k1 = k2;  // Error
         ~~
-!!! error TS2322: Type 'keyof (T & U)' is not assignable to type 'keyof (T | U)'.
+!!! error TS2322: Type 'keyof T | keyof U' is not assignable to type 'keyof (T | U)'.
+!!! error TS2322:   Type 'keyof T' is not assignable to type 'keyof (T | U)'.
         k2 = k1;
     }
     
diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.types b/tests/baselines/reference/keyofAndIndexedAccessErrors.types
index 0c51d3a575c12..bcd3878013d24 100644
--- a/tests/baselines/reference/keyofAndIndexedAccessErrors.types
+++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.types
@@ -243,13 +243,13 @@ function f10(shape: Shape) {
 }
 
 function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
->f20 : <T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) => void
+>f20 : <T, U>(k1: keyof (T | U), k2: keyof T | keyof U, o1: T | U, o2: T & U) => void
 >T : T
 >U : U
 >k1 : keyof (T | U)
 >T : T
 >U : U
->k2 : keyof (T & U)
+>k2 : keyof T | keyof U
 >T : T
 >U : U
 >o1 : T | U
@@ -265,9 +265,9 @@ function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
 >k1 : keyof (T | U)
 
     o1[k2];   // Error
->o1[k2] : (T | U)[keyof (T & U)]
+>o1[k2] : (T | U)[keyof T | keyof U]
 >o1 : T | U
->k2 : keyof (T & U)
+>k2 : keyof T | keyof U
 
     o2[k1];
 >o2[k1] : (T & U)[keyof (T | U)]
@@ -275,9 +275,9 @@ function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
 >k1 : keyof (T | U)
 
     o2[k2];
->o2[k2] : (T & U)[keyof (T & U)]
+>o2[k2] : (T & U)[keyof T | keyof U]
 >o2 : T & U
->k2 : keyof (T & U)
+>k2 : keyof T | keyof U
 
     o1 = o2;
 >o1 = o2 : T & U
@@ -290,13 +290,13 @@ function f20<T, U>(k1: keyof (T | U), k2: keyof (T & U), o1: T | U, o2: T & U) {
 >o1 : T | U
 
     k1 = k2;  // Error
->k1 = k2 : keyof (T & U)
+>k1 = k2 : keyof T | keyof U
 >k1 : keyof (T | U)
->k2 : keyof (T & U)
+>k2 : keyof T | keyof U
 
     k2 = k1;
 >k2 = k1 : keyof (T | U)
->k2 : keyof (T & U)
+>k2 : keyof T | keyof U
 >k1 : keyof (T | U)
 }
 

From 95bb156a3e3064ccc6c0a5fc5a92e652c84a7872 Mon Sep 17 00:00:00 2001
From: Anders Hejlsberg <andersh@microsoft.com>
Date: Fri, 2 Mar 2018 09:26:52 -0800
Subject: [PATCH 3/4] Add tests

---
 .../types/keyof/keyofIntersection.ts          | 29 +++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 tests/cases/conformance/types/keyof/keyofIntersection.ts

diff --git a/tests/cases/conformance/types/keyof/keyofIntersection.ts b/tests/cases/conformance/types/keyof/keyofIntersection.ts
new file mode 100644
index 0000000000000..f570a873242e0
--- /dev/null
+++ b/tests/cases/conformance/types/keyof/keyofIntersection.ts
@@ -0,0 +1,29 @@
+// @strict: true
+// @declaration: true
+
+type A = { a: string };
+type B = { b: string };
+
+type T01 = keyof (A & B);  // "a" | "b"
+type T02<T> = keyof (T & B);  // "b" | keyof T
+type T03<U> = keyof (A & U);  // "a" | keyof U
+type T04<T, U> = keyof (T & U);  // keyof T | keyof U
+type T05 = T02<A>;  // "a" | "b"
+type T06 = T03<B>;  // "a" | "b"
+type T07 = T04<A, B>;  // "a" | "b"
+
+// Repros from #22291
+
+type Example1<T extends string, U extends string> = keyof (Record<T, any> & Record<U, any>);
+type Result1 = Example1<'x', 'y'>;  // "x" | "y"
+
+type Result2 = keyof (Record<'x', any> & Record<'y', any>);  // "x" | "y"
+
+type Example3<T extends string> = keyof (Record<T, any>);
+type Result3 = Example3<'x' | 'y'>;  // "x" | "y"
+
+type Example4<T extends string, U extends string> = (Record<T, any> & Record<U, any>);
+type Result4 = keyof Example4<'x', 'y'>;  // "x" | "y"
+
+type Example5<T, U> = keyof (T & U);
+type Result5 = Example5<Record<'x', any>, Record<'y', any>>;  // "x" | "y"

From 886191390ed413ce70277e70063a5fa65c3fe901 Mon Sep 17 00:00:00 2001
From: Anders Hejlsberg <andersh@microsoft.com>
Date: Fri, 2 Mar 2018 09:27:07 -0800
Subject: [PATCH 4/4] Accept new baselines

---
 .../baselines/reference/keyofIntersection.js  |  56 ++++++++++
 .../reference/keyofIntersection.symbols       | 105 ++++++++++++++++++
 .../reference/keyofIntersection.types         | 105 ++++++++++++++++++
 3 files changed, 266 insertions(+)
 create mode 100644 tests/baselines/reference/keyofIntersection.js
 create mode 100644 tests/baselines/reference/keyofIntersection.symbols
 create mode 100644 tests/baselines/reference/keyofIntersection.types

diff --git a/tests/baselines/reference/keyofIntersection.js b/tests/baselines/reference/keyofIntersection.js
new file mode 100644
index 0000000000000..3b6fc7eea1b72
--- /dev/null
+++ b/tests/baselines/reference/keyofIntersection.js
@@ -0,0 +1,56 @@
+//// [keyofIntersection.ts]
+type A = { a: string };
+type B = { b: string };
+
+type T01 = keyof (A & B);  // "a" | "b"
+type T02<T> = keyof (T & B);  // "b" | keyof T
+type T03<U> = keyof (A & U);  // "a" | keyof U
+type T04<T, U> = keyof (T & U);  // keyof T | keyof U
+type T05 = T02<A>;  // "a" | "b"
+type T06 = T03<B>;  // "a" | "b"
+type T07 = T04<A, B>;  // "a" | "b"
+
+// Repros from #22291
+
+type Example1<T extends string, U extends string> = keyof (Record<T, any> & Record<U, any>);
+type Result1 = Example1<'x', 'y'>;  // "x" | "y"
+
+type Result2 = keyof (Record<'x', any> & Record<'y', any>);  // "x" | "y"
+
+type Example3<T extends string> = keyof (Record<T, any>);
+type Result3 = Example3<'x' | 'y'>;  // "x" | "y"
+
+type Example4<T extends string, U extends string> = (Record<T, any> & Record<U, any>);
+type Result4 = keyof Example4<'x', 'y'>;  // "x" | "y"
+
+type Example5<T, U> = keyof (T & U);
+type Result5 = Example5<Record<'x', any>, Record<'y', any>>;  // "x" | "y"
+
+
+//// [keyofIntersection.js]
+"use strict";
+
+
+//// [keyofIntersection.d.ts]
+declare type A = {
+    a: string;
+};
+declare type B = {
+    b: string;
+};
+declare type T01 = keyof (A & B);
+declare type T02<T> = keyof (T & B);
+declare type T03<U> = keyof (A & U);
+declare type T04<T, U> = keyof (T & U);
+declare type T05 = T02<A>;
+declare type T06 = T03<B>;
+declare type T07 = T04<A, B>;
+declare type Example1<T extends string, U extends string> = keyof (Record<T, any> & Record<U, any>);
+declare type Result1 = Example1<'x', 'y'>;
+declare type Result2 = keyof (Record<'x', any> & Record<'y', any>);
+declare type Example3<T extends string> = keyof (Record<T, any>);
+declare type Result3 = Example3<'x' | 'y'>;
+declare type Example4<T extends string, U extends string> = (Record<T, any> & Record<U, any>);
+declare type Result4 = keyof Example4<'x', 'y'>;
+declare type Example5<T, U> = keyof (T & U);
+declare type Result5 = Example5<Record<'x', any>, Record<'y', any>>;
diff --git a/tests/baselines/reference/keyofIntersection.symbols b/tests/baselines/reference/keyofIntersection.symbols
new file mode 100644
index 0000000000000..aac8341f36350
--- /dev/null
+++ b/tests/baselines/reference/keyofIntersection.symbols
@@ -0,0 +1,105 @@
+=== tests/cases/conformance/types/keyof/keyofIntersection.ts ===
+type A = { a: string };
+>A : Symbol(A, Decl(keyofIntersection.ts, 0, 0))
+>a : Symbol(a, Decl(keyofIntersection.ts, 0, 10))
+
+type B = { b: string };
+>B : Symbol(B, Decl(keyofIntersection.ts, 0, 23))
+>b : Symbol(b, Decl(keyofIntersection.ts, 1, 10))
+
+type T01 = keyof (A & B);  // "a" | "b"
+>T01 : Symbol(T01, Decl(keyofIntersection.ts, 1, 23))
+>A : Symbol(A, Decl(keyofIntersection.ts, 0, 0))
+>B : Symbol(B, Decl(keyofIntersection.ts, 0, 23))
+
+type T02<T> = keyof (T & B);  // "b" | keyof T
+>T02 : Symbol(T02, Decl(keyofIntersection.ts, 3, 25))
+>T : Symbol(T, Decl(keyofIntersection.ts, 4, 9))
+>T : Symbol(T, Decl(keyofIntersection.ts, 4, 9))
+>B : Symbol(B, Decl(keyofIntersection.ts, 0, 23))
+
+type T03<U> = keyof (A & U);  // "a" | keyof U
+>T03 : Symbol(T03, Decl(keyofIntersection.ts, 4, 28))
+>U : Symbol(U, Decl(keyofIntersection.ts, 5, 9))
+>A : Symbol(A, Decl(keyofIntersection.ts, 0, 0))
+>U : Symbol(U, Decl(keyofIntersection.ts, 5, 9))
+
+type T04<T, U> = keyof (T & U);  // keyof T | keyof U
+>T04 : Symbol(T04, Decl(keyofIntersection.ts, 5, 28))
+>T : Symbol(T, Decl(keyofIntersection.ts, 6, 9))
+>U : Symbol(U, Decl(keyofIntersection.ts, 6, 11))
+>T : Symbol(T, Decl(keyofIntersection.ts, 6, 9))
+>U : Symbol(U, Decl(keyofIntersection.ts, 6, 11))
+
+type T05 = T02<A>;  // "a" | "b"
+>T05 : Symbol(T05, Decl(keyofIntersection.ts, 6, 31))
+>T02 : Symbol(T02, Decl(keyofIntersection.ts, 3, 25))
+>A : Symbol(A, Decl(keyofIntersection.ts, 0, 0))
+
+type T06 = T03<B>;  // "a" | "b"
+>T06 : Symbol(T06, Decl(keyofIntersection.ts, 7, 18))
+>T03 : Symbol(T03, Decl(keyofIntersection.ts, 4, 28))
+>B : Symbol(B, Decl(keyofIntersection.ts, 0, 23))
+
+type T07 = T04<A, B>;  // "a" | "b"
+>T07 : Symbol(T07, Decl(keyofIntersection.ts, 8, 18))
+>T04 : Symbol(T04, Decl(keyofIntersection.ts, 5, 28))
+>A : Symbol(A, Decl(keyofIntersection.ts, 0, 0))
+>B : Symbol(B, Decl(keyofIntersection.ts, 0, 23))
+
+// Repros from #22291
+
+type Example1<T extends string, U extends string> = keyof (Record<T, any> & Record<U, any>);
+>Example1 : Symbol(Example1, Decl(keyofIntersection.ts, 9, 21))
+>T : Symbol(T, Decl(keyofIntersection.ts, 13, 14))
+>U : Symbol(U, Decl(keyofIntersection.ts, 13, 31))
+>Record : Symbol(Record, Decl(lib.d.ts, --, --))
+>T : Symbol(T, Decl(keyofIntersection.ts, 13, 14))
+>Record : Symbol(Record, Decl(lib.d.ts, --, --))
+>U : Symbol(U, Decl(keyofIntersection.ts, 13, 31))
+
+type Result1 = Example1<'x', 'y'>;  // "x" | "y"
+>Result1 : Symbol(Result1, Decl(keyofIntersection.ts, 13, 92))
+>Example1 : Symbol(Example1, Decl(keyofIntersection.ts, 9, 21))
+
+type Result2 = keyof (Record<'x', any> & Record<'y', any>);  // "x" | "y"
+>Result2 : Symbol(Result2, Decl(keyofIntersection.ts, 14, 34))
+>Record : Symbol(Record, Decl(lib.d.ts, --, --))
+>Record : Symbol(Record, Decl(lib.d.ts, --, --))
+
+type Example3<T extends string> = keyof (Record<T, any>);
+>Example3 : Symbol(Example3, Decl(keyofIntersection.ts, 16, 59))
+>T : Symbol(T, Decl(keyofIntersection.ts, 18, 14))
+>Record : Symbol(Record, Decl(lib.d.ts, --, --))
+>T : Symbol(T, Decl(keyofIntersection.ts, 18, 14))
+
+type Result3 = Example3<'x' | 'y'>;  // "x" | "y"
+>Result3 : Symbol(Result3, Decl(keyofIntersection.ts, 18, 57))
+>Example3 : Symbol(Example3, Decl(keyofIntersection.ts, 16, 59))
+
+type Example4<T extends string, U extends string> = (Record<T, any> & Record<U, any>);
+>Example4 : Symbol(Example4, Decl(keyofIntersection.ts, 19, 35))
+>T : Symbol(T, Decl(keyofIntersection.ts, 21, 14))
+>U : Symbol(U, Decl(keyofIntersection.ts, 21, 31))
+>Record : Symbol(Record, Decl(lib.d.ts, --, --))
+>T : Symbol(T, Decl(keyofIntersection.ts, 21, 14))
+>Record : Symbol(Record, Decl(lib.d.ts, --, --))
+>U : Symbol(U, Decl(keyofIntersection.ts, 21, 31))
+
+type Result4 = keyof Example4<'x', 'y'>;  // "x" | "y"
+>Result4 : Symbol(Result4, Decl(keyofIntersection.ts, 21, 86))
+>Example4 : Symbol(Example4, Decl(keyofIntersection.ts, 19, 35))
+
+type Example5<T, U> = keyof (T & U);
+>Example5 : Symbol(Example5, Decl(keyofIntersection.ts, 22, 40))
+>T : Symbol(T, Decl(keyofIntersection.ts, 24, 14))
+>U : Symbol(U, Decl(keyofIntersection.ts, 24, 16))
+>T : Symbol(T, Decl(keyofIntersection.ts, 24, 14))
+>U : Symbol(U, Decl(keyofIntersection.ts, 24, 16))
+
+type Result5 = Example5<Record<'x', any>, Record<'y', any>>;  // "x" | "y"
+>Result5 : Symbol(Result5, Decl(keyofIntersection.ts, 24, 36))
+>Example5 : Symbol(Example5, Decl(keyofIntersection.ts, 22, 40))
+>Record : Symbol(Record, Decl(lib.d.ts, --, --))
+>Record : Symbol(Record, Decl(lib.d.ts, --, --))
+
diff --git a/tests/baselines/reference/keyofIntersection.types b/tests/baselines/reference/keyofIntersection.types
new file mode 100644
index 0000000000000..f9c312b412046
--- /dev/null
+++ b/tests/baselines/reference/keyofIntersection.types
@@ -0,0 +1,105 @@
+=== tests/cases/conformance/types/keyof/keyofIntersection.ts ===
+type A = { a: string };
+>A : A
+>a : string
+
+type B = { b: string };
+>B : B
+>b : string
+
+type T01 = keyof (A & B);  // "a" | "b"
+>T01 : "b" | "a"
+>A : A
+>B : B
+
+type T02<T> = keyof (T & B);  // "b" | keyof T
+>T02 : keyof T | "b"
+>T : T
+>T : T
+>B : B
+
+type T03<U> = keyof (A & U);  // "a" | keyof U
+>T03 : "a" | keyof U
+>U : U
+>A : A
+>U : U
+
+type T04<T, U> = keyof (T & U);  // keyof T | keyof U
+>T04 : keyof T | keyof U
+>T : T
+>U : U
+>T : T
+>U : U
+
+type T05 = T02<A>;  // "a" | "b"
+>T05 : "b" | "a"
+>T02 : keyof T | "b"
+>A : A
+
+type T06 = T03<B>;  // "a" | "b"
+>T06 : "b" | "a"
+>T03 : "a" | keyof U
+>B : B
+
+type T07 = T04<A, B>;  // "a" | "b"
+>T07 : "b" | "a"
+>T04 : keyof T | keyof U
+>A : A
+>B : B
+
+// Repros from #22291
+
+type Example1<T extends string, U extends string> = keyof (Record<T, any> & Record<U, any>);
+>Example1 : T | U
+>T : T
+>U : U
+>Record : Record<K, T>
+>T : T
+>Record : Record<K, T>
+>U : U
+
+type Result1 = Example1<'x', 'y'>;  // "x" | "y"
+>Result1 : "x" | "y"
+>Example1 : T | U
+
+type Result2 = keyof (Record<'x', any> & Record<'y', any>);  // "x" | "y"
+>Result2 : "x" | "y"
+>Record : Record<K, T>
+>Record : Record<K, T>
+
+type Example3<T extends string> = keyof (Record<T, any>);
+>Example3 : T
+>T : T
+>Record : Record<K, T>
+>T : T
+
+type Result3 = Example3<'x' | 'y'>;  // "x" | "y"
+>Result3 : "x" | "y"
+>Example3 : T
+
+type Example4<T extends string, U extends string> = (Record<T, any> & Record<U, any>);
+>Example4 : Record<T, any> & Record<U, any>
+>T : T
+>U : U
+>Record : Record<K, T>
+>T : T
+>Record : Record<K, T>
+>U : U
+
+type Result4 = keyof Example4<'x', 'y'>;  // "x" | "y"
+>Result4 : "x" | "y"
+>Example4 : Record<T, any> & Record<U, any>
+
+type Example5<T, U> = keyof (T & U);
+>Example5 : keyof T | keyof U
+>T : T
+>U : U
+>T : T
+>U : U
+
+type Result5 = Example5<Record<'x', any>, Record<'y', any>>;  // "x" | "y"
+>Result5 : "x" | "y"
+>Example5 : keyof T | keyof U
+>Record : Record<K, T>
+>Record : Record<K, T>
+