Skip to content

Commit 1e2425e

Browse files
committed
Add tests
1 parent b3b2359 commit 1e2425e

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,45 @@ class OtherPerson {
250250
return getProperty(this, "parts")
251251
}
252252
}
253+
254+
// Modified repro from #12544
255+
256+
function path<T, K1 extends keyof T>(obj: T, key1: K1): T[K1];
257+
function path<T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2];
258+
function path<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
259+
function path(obj: any, ...keys: (string | number)[]): any;
260+
function path(obj: any, ...keys: (string | number)[]): any {
261+
let result = obj;
262+
for (let k of keys) {
263+
result = result[k];
264+
}
265+
return result;
266+
}
267+
268+
type Thing = {
269+
a: { x: number, y: string },
270+
b: boolean
271+
};
272+
273+
274+
function f1(thing: Thing) {
275+
let x1 = path(thing, 'a'); // { x: number, y: string }
276+
let x2 = path(thing, 'a', 'y'); // string
277+
let x3 = path(thing, 'b'); // boolean
278+
let x4 = path(thing, ...['a', 'x']); // any
279+
}
280+
281+
// Repro from comment in #12114
282+
283+
const assignTo2 = <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) =>
284+
(value: T[K1][K2]) => object[key1][key2] = value;
285+
286+
// Modified repro from #12573
287+
288+
declare function one<T>(handler: (t: T) => void): T
289+
var empty = one(() => {}) // inferred as {}, expected
290+
291+
type Handlers<T> = { [K in keyof T]: (t: T[K]) => void }
292+
declare function on<T>(handlerHash: Handlers<T>): T
293+
var hashOfEmpty1 = on({ test: () => {} }); // {}
294+
var hashOfEmpty2 = on({ test: (x: boolean) => {} }); // { test: boolean }

tests/cases/conformance/types/mapped/isomorphicMappedTypeInference.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,29 @@ function f10(foo: Foo) {
120120
let x = validate(foo); // { a: number, readonly b: string }
121121
let y = clone(foo); // { a?: number, b: string }
122122
let z = validateAndClone(foo); // { a: number, b: string }
123-
}
123+
}
124+
125+
// Repro from #12606
126+
127+
type Func<T> = (...args: any[]) => T;
128+
type Spec<T> = {
129+
[P in keyof T]: Func<T[P]> | Spec<T[P]> ;
130+
};
131+
132+
/**
133+
* Given a spec object recursively mapping properties to functions, creates a function
134+
* producing an object of the same structure, by mapping each property to the result
135+
* of calling its associated function with the supplied arguments.
136+
*/
137+
declare function applySpec<T>(obj: Spec<T>): (...args: any[]) => T;
138+
139+
// Infers g1: (...args: any[]) => { sum: number, nested: { mul: string } }
140+
var g1 = applySpec({
141+
sum: (a: any) => 3,
142+
nested: {
143+
mul: (b: any) => "n"
144+
}
145+
});
146+
147+
// Infers g2: (...args: any[]) => { foo: { bar: { baz: boolean } } }
148+
var g2 = applySpec({ foo: { bar: { baz: (x: any) => true } } });

0 commit comments

Comments
 (0)