Skip to content

Commit 37f15cc

Browse files
authored
Print deferred mapped symbols 1 level deep (microsoft#21311)
* Print deferred mapped symbols 1 level deep Previously, deferred mapped symbols would not print their type at all; it would always print as `any`. This differed from the older behaviour that printed it forever if necessary. As a compromise, we now print deferred mapped symbosl 1 level deep before giving up and printing `any`. This should cover the most common uses of mapped types. * Use context flags instead of a global
1 parent 7b9ceb8 commit 37f15cc

15 files changed

Lines changed: 127 additions & 102 deletions

src/compiler/checker.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3215,7 +3215,8 @@ namespace ts {
32153215
context.tracker.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(propertySymbol.escapedName));
32163216
}
32173217
}
3218-
const propertyType = getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped ? anyType : getTypeOfSymbol(propertySymbol);
3218+
const propertyType = getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped && context.flags & NodeBuilderFlags.InReverseMappedType ?
3219+
anyType : getTypeOfSymbol(propertySymbol);
32193220
const saveEnclosingDeclaration = context.enclosingDeclaration;
32203221
context.enclosingDeclaration = undefined;
32213222
if (getCheckFlags(propertySymbol) & CheckFlags.Late) {
@@ -3238,7 +3239,10 @@ namespace ts {
32383239
}
32393240
}
32403241
else {
3242+
const savedFlags = context.flags;
3243+
context.flags |= !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped) ? NodeBuilderFlags.InReverseMappedType : 0;
32413244
const propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : createKeywordTypeNode(SyntaxKind.AnyKeyword);
3245+
context.flags = savedFlags;
32423246

32433247
const modifiers = isReadonlySymbol(propertySymbol) ? [createToken(SyntaxKind.ReadonlyKeyword)] : undefined;
32443248
const propertySignature = createPropertySignature(

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2983,6 +2983,7 @@ namespace ts {
29832983
InObjectTypeLiteral = 1 << 22,
29842984
InTypeAlias = 1 << 23, // Writing type in type alias declaration
29852985
InInitialEntityName = 1 << 24, // Set when writing the LHS of an entity name or entity name expression
2986+
InReverseMappedType = 1 << 25,
29862987
}
29872988

29882989
// Ensure the shared flags between this and `NodeBuilderFlags` stay in alignment

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,6 +1838,7 @@ declare namespace ts {
18381838
InObjectTypeLiteral = 4194304,
18391839
InTypeAlias = 8388608,
18401840
InInitialEntityName = 16777216,
1841+
InReverseMappedType = 33554432,
18411842
}
18421843
enum TypeFormatFlags {
18431844
None = 0,

tests/baselines/reference/api/typescript.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,6 +1838,7 @@ declare namespace ts {
18381838
InObjectTypeLiteral = 4194304,
18391839
InTypeAlias = 8388608,
18401840
InInitialEntityName = 16777216,
1841+
InReverseMappedType = 33554432,
18411842
}
18421843
enum TypeFormatFlags {
18431844
None = 0,

tests/baselines/reference/isomorphicMappedTypeInference.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,15 @@ declare type Spec<T> = {
308308
*/
309309
declare function applySpec<T>(obj: Spec<T>): (...args: any[]) => T;
310310
declare var g1: (...args: any[]) => {
311-
sum: any;
312-
nested: any;
311+
sum: number;
312+
nested: {
313+
mul: any;
314+
};
313315
};
314316
declare var g2: (...args: any[]) => {
315-
foo: any;
317+
foo: {
318+
bar: any;
319+
};
316320
};
317321
declare const foo: <T>(object: T, partial: Partial<T>) => T;
318322
declare let o: {

tests/baselines/reference/isomorphicMappedTypeInference.types

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -203,15 +203,15 @@ function f2() {
203203

204204
};
205205
let v = unboxify(b);
206-
>v : { a: any; b: any; c: any; }
207-
>unboxify(b) : { a: any; b: any; c: any; }
206+
>v : { a: number; b: string; c: boolean; }
207+
>unboxify(b) : { a: number; b: string; c: boolean; }
208208
>unboxify : <T>(obj: Boxified<T>) => T
209209
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
210210

211211
let x: number = v.a;
212212
>x : number
213213
>v.a : number
214-
>v : { a: any; b: any; c: any; }
214+
>v : { a: number; b: string; c: boolean; }
215215
>a : number
216216
}
217217

@@ -277,11 +277,11 @@ function f4() {
277277

278278
};
279279
b = boxify(unboxify(b));
280-
>b = boxify(unboxify(b)) : Boxified<{ a: any; b: any; c: any; }>
280+
>b = boxify(unboxify(b)) : Boxified<{ a: number; b: string; c: boolean; }>
281281
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
282-
>boxify(unboxify(b)) : Boxified<{ a: any; b: any; c: any; }>
282+
>boxify(unboxify(b)) : Boxified<{ a: number; b: string; c: boolean; }>
283283
>boxify : <T>(obj: T) => Boxified<T>
284-
>unboxify(b) : { a: any; b: any; c: any; }
284+
>unboxify(b) : { a: number; b: string; c: boolean; }
285285
>unboxify : <T>(obj: Boxified<T>) => T
286286
>b : { a: Box<number>; b: Box<string>; c: Box<boolean>; }
287287

@@ -338,15 +338,15 @@ function f5(s: string) {
338338

339339
});
340340
let v = unboxify(b);
341-
>v : { a: any; b: any; c: any; }
342-
>unboxify(b) : { a: any; b: any; c: any; }
341+
>v : { a: string | number | boolean; b: string | number | boolean; c: string | number | boolean; }
342+
>unboxify(b) : { a: string | number | boolean; b: string | number | boolean; c: string | number | boolean; }
343343
>unboxify : <T>(obj: Boxified<T>) => T
344344
>b : { a: Box<number> | Box<string> | Box<boolean>; b: Box<number> | Box<string> | Box<boolean>; c: Box<number> | Box<string> | Box<boolean>; }
345345

346346
let x: string | number | boolean = v.a;
347347
>x : string | number | boolean
348348
>v.a : string | number | boolean
349-
>v : { a: any; b: any; c: any; }
349+
>v : { a: string | number | boolean; b: string | number | boolean; c: string | number | boolean; }
350350
>a : string | number | boolean
351351
}
352352

@@ -449,20 +449,20 @@ function f10(foo: Foo) {
449449
>Foo : Foo
450450

451451
let x = validate(foo); // { a: number, readonly b: string }
452-
>x : { a: any; readonly b: any; }
453-
>validate(foo) : { a: any; readonly b: any; }
452+
>x : { a: number; readonly b: string; }
453+
>validate(foo) : { a: number; readonly b: string; }
454454
>validate : <T>(obj: { [P in keyof T]?: T[P] | undefined; }) => T
455455
>foo : Foo
456456

457457
let y = clone(foo); // { a?: number, b: string }
458-
>y : { a?: any; b: any; }
459-
>clone(foo) : { a?: any; b: any; }
458+
>y : { a?: number | undefined; b: string; }
459+
>clone(foo) : { a?: number | undefined; b: string; }
460460
>clone : <T>(obj: { readonly [P in keyof T]: T[P]; }) => T
461461
>foo : Foo
462462

463463
let z = validateAndClone(foo); // { a: number, b: string }
464-
>z : { a: any; b: any; }
465-
>validateAndClone(foo) : { a: any; b: any; }
464+
>z : { a: number; b: string; }
465+
>validateAndClone(foo) : { a: number; b: string; }
466466
>validateAndClone : <T>(obj: { readonly [P in keyof T]?: T[P] | undefined; }) => T
467467
>foo : Foo
468468
}
@@ -507,8 +507,8 @@ declare function applySpec<T>(obj: Spec<T>): (...args: any[]) => T;
507507

508508
// Infers g1: (...args: any[]) => { sum: number, nested: { mul: string } }
509509
var g1 = applySpec({
510-
>g1 : (...args: any[]) => { sum: any; nested: any; }
511-
>applySpec({ sum: (a: any) => 3, nested: { mul: (b: any) => "n" }}) : (...args: any[]) => { sum: any; nested: any; }
510+
>g1 : (...args: any[]) => { sum: number; nested: { mul: any; }; }
511+
>applySpec({ sum: (a: any) => 3, nested: { mul: (b: any) => "n" }}) : (...args: any[]) => { sum: number; nested: { mul: any; }; }
512512
>applySpec : <T>(obj: Spec<T>) => (...args: any[]) => T
513513
>{ sum: (a: any) => 3, nested: { mul: (b: any) => "n" }} : { sum: (a: any) => number; nested: { mul: (b: any) => string; }; }
514514

@@ -532,8 +532,8 @@ var g1 = applySpec({
532532

533533
// Infers g2: (...args: any[]) => { foo: { bar: { baz: boolean } } }
534534
var g2 = applySpec({ foo: { bar: { baz: (x: any) => true } } });
535-
>g2 : (...args: any[]) => { foo: any; }
536-
>applySpec({ foo: { bar: { baz: (x: any) => true } } }) : (...args: any[]) => { foo: any; }
535+
>g2 : (...args: any[]) => { foo: { bar: any; }; }
536+
>applySpec({ foo: { bar: { baz: (x: any) => true } } }) : (...args: any[]) => { foo: { bar: any; }; }
537537
>applySpec : <T>(obj: Spec<T>) => (...args: any[]) => T
538538
>{ foo: { bar: { baz: (x: any) => true } } } : { foo: { bar: { baz: (x: any) => boolean; }; }; }
539539
>foo : { bar: { baz: (x: any) => boolean; }; }

tests/baselines/reference/keyofAndIndexedAccess.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,10 +1122,10 @@ declare type Handlers<T> = {
11221122
};
11231123
declare function on<T>(handlerHash: Handlers<T>): T;
11241124
declare var hashOfEmpty1: {
1125-
test: any;
1125+
test: {};
11261126
};
11271127
declare var hashOfEmpty2: {
1128-
test: any;
1128+
test: boolean;
11291129
};
11301130
interface Options1<Data, Computed> {
11311131
data?: Data;

tests/baselines/reference/keyofAndIndexedAccess.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,16 +1793,16 @@ declare function on<T>(handlerHash: Handlers<T>): T
17931793
>T : T
17941794

17951795
var hashOfEmpty1 = on({ test: () => {} }); // {}
1796-
>hashOfEmpty1 : { test: any; }
1797-
>on({ test: () => {} }) : { test: any; }
1796+
>hashOfEmpty1 : { test: {}; }
1797+
>on({ test: () => {} }) : { test: {}; }
17981798
>on : <T>(handlerHash: Handlers<T>) => T
17991799
>{ test: () => {} } : { test: () => void; }
18001800
>test : () => void
18011801
>() => {} : () => void
18021802

18031803
var hashOfEmpty2 = on({ test: (x: boolean) => {} }); // { test: boolean }
1804-
>hashOfEmpty2 : { test: any; }
1805-
>on({ test: (x: boolean) => {} }) : { test: any; }
1804+
>hashOfEmpty2 : { test: boolean; }
1805+
>on({ test: (x: boolean) => {} }) : { test: boolean; }
18061806
>on : <T>(handlerHash: Handlers<T>) => T
18071807
>{ test: (x: boolean) => {} } : { test: (x: boolean) => void; }
18081808
>test : (x: boolean) => void

tests/baselines/reference/mappedTypeInferenceErrors.errors.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
tests/cases/conformance/types/mapped/mappedTypeInferenceErrors.ts(9,5): error TS2345: Argument of type '{ props: { x: number; y: number; }; computed: { bar(): number; baz: number; }; }' is not assignable to parameter of type '{ props: { x: number; y: number; }; computed: ComputedOf<{ bar: any; baz: any; }>; } & ThisType<{ x: number; y: number; } & { bar: any; baz: any; }>'.
2-
Type '{ props: { x: number; y: number; }; computed: { bar(): number; baz: number; }; }' is not assignable to type '{ props: { x: number; y: number; }; computed: ComputedOf<{ bar: any; baz: any; }>; }'.
1+
tests/cases/conformance/types/mapped/mappedTypeInferenceErrors.ts(9,5): error TS2345: Argument of type '{ props: { x: number; y: number; }; computed: { bar(): number; baz: number; }; }' is not assignable to parameter of type '{ props: { x: number; y: number; }; computed: ComputedOf<{ bar: number; baz: {}; }>; } & ThisType<{ x: number; y: number; } & { bar: number; baz: {}; }>'.
2+
Type '{ props: { x: number; y: number; }; computed: { bar(): number; baz: number; }; }' is not assignable to type '{ props: { x: number; y: number; }; computed: ComputedOf<{ bar: number; baz: {}; }>; }'.
33
Types of property 'computed' are incompatible.
4-
Type '{ bar(): number; baz: number; }' is not assignable to type 'ComputedOf<{ bar: any; baz: any; }>'.
4+
Type '{ bar(): number; baz: number; }' is not assignable to type 'ComputedOf<{ bar: number; baz: {}; }>'.
55
Types of property 'baz' are incompatible.
66
Type 'number' is not assignable to type '() => {}'.
77

@@ -35,10 +35,10 @@ tests/cases/conformance/types/mapped/mappedTypeInferenceErrors.ts(9,5): error TS
3535
~~~~~
3636
});
3737
~
38-
!!! error TS2345: Argument of type '{ props: { x: number; y: number; }; computed: { bar(): number; baz: number; }; }' is not assignable to parameter of type '{ props: { x: number; y: number; }; computed: ComputedOf<{ bar: any; baz: any; }>; } & ThisType<{ x: number; y: number; } & { bar: any; baz: any; }>'.
39-
!!! error TS2345: Type '{ props: { x: number; y: number; }; computed: { bar(): number; baz: number; }; }' is not assignable to type '{ props: { x: number; y: number; }; computed: ComputedOf<{ bar: any; baz: any; }>; }'.
38+
!!! error TS2345: Argument of type '{ props: { x: number; y: number; }; computed: { bar(): number; baz: number; }; }' is not assignable to parameter of type '{ props: { x: number; y: number; }; computed: ComputedOf<{ bar: number; baz: {}; }>; } & ThisType<{ x: number; y: number; } & { bar: number; baz: {}; }>'.
39+
!!! error TS2345: Type '{ props: { x: number; y: number; }; computed: { bar(): number; baz: number; }; }' is not assignable to type '{ props: { x: number; y: number; }; computed: ComputedOf<{ bar: number; baz: {}; }>; }'.
4040
!!! error TS2345: Types of property 'computed' are incompatible.
41-
!!! error TS2345: Type '{ bar(): number; baz: number; }' is not assignable to type 'ComputedOf<{ bar: any; baz: any; }>'.
41+
!!! error TS2345: Type '{ bar(): number; baz: number; }' is not assignable to type 'ComputedOf<{ bar: number; baz: {}; }>'.
4242
!!! error TS2345: Types of property 'baz' are incompatible.
4343
!!! error TS2345: Type 'number' is not assignable to type '() => {}'.
4444

0 commit comments

Comments
 (0)