Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions internal/checker/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,18 +427,18 @@ const (
TypeFlagsUniqueESSymbol TypeFlags = 1 << 14 // unique symbol
TypeFlagsEnumLiteral TypeFlags = 1 << 15 // Always combined with StringLiteral, NumberLiteral, or Union
TypeFlagsEnum TypeFlags = 1 << 16 // Numeric computed enum member value (must be right after EnumLiteral, see getSortOrderFlags)
TypeFlagsNever TypeFlags = 1 << 17 // Never type
TypeFlagsTypeParameter TypeFlags = 1 << 18 // Type parameter
TypeFlagsObject TypeFlags = 1 << 19 // Object type
TypeFlagsUnion TypeFlags = 1 << 20 // Union (T | U)
TypeFlagsIntersection TypeFlags = 1 << 21 // Intersection (T & U)
TypeFlagsIndex TypeFlags = 1 << 22 // keyof T
TypeFlagsIndexedAccess TypeFlags = 1 << 23 // T[K]
TypeFlagsConditional TypeFlags = 1 << 24 // T extends U ? X : Y
TypeFlagsSubstitution TypeFlags = 1 << 25 // Type parameter substitution
TypeFlagsNonPrimitive TypeFlags = 1 << 26 // intrinsic object type
TypeFlagsTemplateLiteral TypeFlags = 1 << 27 // Template literal type
TypeFlagsStringMapping TypeFlags = 1 << 28 // Uppercase/Lowercase type
TypeFlagsNonPrimitive TypeFlags = 1 << 17 // intrinsic object type
TypeFlagsNever TypeFlags = 1 << 18 // Never type
TypeFlagsTypeParameter TypeFlags = 1 << 19 // Type parameter
TypeFlagsObject TypeFlags = 1 << 20 // Object type
TypeFlagsIndex TypeFlags = 1 << 21 // keyof T
TypeFlagsIndexedAccess TypeFlags = 1 << 22 // T[K]
TypeFlagsConditional TypeFlags = 1 << 23 // T extends U ? X : Y
TypeFlagsSubstitution TypeFlags = 1 << 24 // Type parameter substitution
TypeFlagsTemplateLiteral TypeFlags = 1 << 25 // Template literal type
TypeFlagsStringMapping TypeFlags = 1 << 26 // Uppercase/Lowercase type
TypeFlagsUnion TypeFlags = 1 << 27 // Union (T | U)
TypeFlagsIntersection TypeFlags = 1 << 28 // Intersection (T & U)
TypeFlagsReserved1 TypeFlags = 1 << 29 // Used by union/intersection type construction
TypeFlagsReserved2 TypeFlags = 1 << 30 // Used by union/intersection type construction
TypeFlagsReserved3 TypeFlags = 1 << 31
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//// [tests/cases/compiler/objectSubtypeReduction.ts] ////

=== objectSubtypeReduction.ts ===
// https://github.com/microsoft/typescript-go/issues/1164

function foo(x?: object) {
>foo : Symbol(foo, Decl(objectSubtypeReduction.ts, 0, 0))
>x : Symbol(x, Decl(objectSubtypeReduction.ts, 2, 13))

return Object.entries(x || {})
>Object.entries(x || {}) .sort : Symbol(sort, Decl(lib.es5.d.ts, --, --))
>Object.entries : Symbol(entries, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>entries : Symbol(entries, Decl(lib.es2017.object.d.ts, --, --), Decl(lib.es2017.object.d.ts, --, --))
>x : Symbol(x, Decl(objectSubtypeReduction.ts, 2, 13))

.sort(([k1, v1], [k2, v2]) => v1.name.localeCompare(v2.name));
>sort : Symbol(sort, Decl(lib.es5.d.ts, --, --))
>k1 : Symbol(k1, Decl(objectSubtypeReduction.ts, 4, 16))
>v1 : Symbol(v1, Decl(objectSubtypeReduction.ts, 4, 19))
>k2 : Symbol(k2, Decl(objectSubtypeReduction.ts, 4, 26))
>v2 : Symbol(v2, Decl(objectSubtypeReduction.ts, 4, 29))
>v1 : Symbol(v1, Decl(objectSubtypeReduction.ts, 4, 19))
>v2 : Symbol(v2, Decl(objectSubtypeReduction.ts, 4, 29))
}

38 changes: 38 additions & 0 deletions testdata/baselines/reference/compiler/objectSubtypeReduction.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//// [tests/cases/compiler/objectSubtypeReduction.ts] ////

=== objectSubtypeReduction.ts ===
// https://github.com/microsoft/typescript-go/issues/1164

function foo(x?: object) {
>foo : (x?: object | undefined) => [string, any][]
>x : object | undefined

return Object.entries(x || {})
>Object.entries(x || {}) .sort(([k1, v1], [k2, v2]) => v1.name.localeCompare(v2.name)) : [string, any][]
>Object.entries(x || {}) .sort : (compareFn?: ((a: [string, any], b: [string, any]) => number) | undefined) => [string, any][]
>Object.entries(x || {}) : [string, any][]
>Object.entries : { <T>(o: ArrayLike<T> | { [s: string]: T; }): [string, T][]; (o: {}): [string, any][]; }
>Object : ObjectConstructor
>entries : { <T>(o: ArrayLike<T> | { [s: string]: T; }): [string, T][]; (o: {}): [string, any][]; }
>x || {} : object
>x : object | undefined
>{} : {}

.sort(([k1, v1], [k2, v2]) => v1.name.localeCompare(v2.name));
>sort : (compareFn?: ((a: [string, any], b: [string, any]) => number) | undefined) => [string, any][]
>([k1, v1], [k2, v2]) => v1.name.localeCompare(v2.name) : ([k1, v1]: [string, any], [k2, v2]: [string, any]) => any
>k1 : string
>v1 : any
>k2 : string
>v2 : any
>v1.name.localeCompare(v2.name) : any
>v1.name.localeCompare : any
>v1.name : any
>v1 : any
>name : any
>localeCompare : any
>v2.name : any
>v2 : any
>name : any
}

Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@

Object.freeze({
>Object.freeze({ foo() { return Object.freeze('a'); },}) : Readonly<{ foo(): string; }>
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>{ foo() { return Object.freeze('a'); },} : { foo(): string; }

foo() {
>foo : () => string

return Object.freeze('a');
>Object.freeze('a') : string
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>'a' : "a"

},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
Object.freeze({
>Object.freeze({ foo() { return Object.freeze('a'); },}) : Readonly<{ foo(): string; }>
->Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | null | undefined | object; }, U extends string | bigint | number | boolean | symbol>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
->freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | null | undefined | object; }, U extends string | bigint | number | boolean | symbol>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>{ foo() { return Object.freeze('a'); },} : { foo(): string; }

foo() {
Expand All @@ -17,10 +17,10 @@
return Object.freeze('a');
>Object.freeze('a') : string
->Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | null | undefined | object; }, U extends string | bigint | number | boolean | symbol>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
->freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | null | undefined | object; }, U extends string | bigint | number | boolean | symbol>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U | null | undefined; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>'a' : "a"

},
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

Object.freeze({
>Object.freeze({ f: function () { }}) : Readonly<{ f: () => void; }>
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>{ f: function () { }} : { f: () => void; }

f: function () { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
Object.freeze({
>Object.freeze({ f: function () { }}) : Readonly<{ f: () => void; }>
->Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | null | undefined | object; }, U extends string | bigint | number | boolean | symbol>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
->freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | null | undefined | object; }, U extends string | bigint | number | boolean | symbol>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
+>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>{ f: function () { }} : { f: () => void; }

f: function () { }
Original file line number Diff line number Diff line change
Expand Up @@ -860,15 +860,15 @@ function getConfigOrDefault<T extends keyof Config>(
>key : T

const assertedCheck = userValue ? userValue! : defaultValue;
>assertedCheck : NonNullable<Partial<Config>[T]>
>userValue ? userValue! : defaultValue : NonNullable<Partial<Config>[T]>
>assertedCheck : Config[T]
>userValue ? userValue! : defaultValue : Config[T]
>userValue : Partial<Config>[T]
>userValue! : NonNullable<Partial<Config>[T]>
>userValue : NonNullable<Partial<Config>[T]>
>defaultValue : Config[T]

return assertedCheck;
>assertedCheck : NonNullable<Partial<Config>[T]>
>assertedCheck : Config[T]
}

// repro from #47523
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,23 @@
+>< K extends KeyOfOriginal, N extends NestedKeyOfOriginalFor<K>>( original: Original, mappedFromOriginal: MappedFromOriginal, key: K, nestedKey: N): [Original[K][N], MappedFromOriginal[K][N]] => { return [original[key][nestedKey], mappedFromOriginal[key][nestedKey]];} : <K extends keyof Original, N extends keyof Original[K]>(original: Original, mappedFromOriginal: SameKeys<Original>, key: K, nestedKey: N) => [Original[K][N], SameKeys<Original>[K][N]]

K extends KeyOfOriginal,
N extends NestedKeyOfOriginalFor<K>
N extends NestedKeyOfOriginalFor<K>
@@= skipped -63, +63 lines =@@
>key : T

const assertedCheck = userValue ? userValue! : defaultValue;
->assertedCheck : NonNullable<Partial<Config>[T]>
->userValue ? userValue! : defaultValue : NonNullable<Partial<Config>[T]>
+>assertedCheck : Config[T]
+>userValue ? userValue! : defaultValue : Config[T]
>userValue : Partial<Config>[T]
>userValue! : NonNullable<Partial<Config>[T]>
>userValue : NonNullable<Partial<Config>[T]>
>defaultValue : Config[T]

return assertedCheck;
->assertedCheck : NonNullable<Partial<Config>[T]>
+>assertedCheck : Config[T]
}

// repro from #47523
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ cbThing(type => {
const Thing = Object.freeze({
>Thing : Readonly<{ a: "thing"; b: "chill"; }>
>Object.freeze({ a: "thing", b: "chill"}) : Readonly<{ a: "thing"; b: "chill"; }>
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>{ a: "thing", b: "chill"} : { a: "thing"; b: "chill"; }

a: "thing",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
const f = Object.freeze(function foo(a: number, b: string) { return false; });
>f : (a: number, b: string) => false
>Object.freeze(function foo(a: number, b: string) { return false; }) : (a: number, b: string) => false
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>function foo(a: number, b: string) { return false; } : (a: number, b: string) => false
>foo : (a: number, b: string) => false
>a : number
Expand All @@ -28,9 +28,9 @@ class C { constructor(a: number) { } }
const c = Object.freeze(C);
>c : typeof C
>Object.freeze(C) : typeof C
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>C : typeof C

new c(1);
Expand All @@ -41,9 +41,9 @@ new c(1);
const a = Object.freeze([1, 2, 3]);
>a : readonly number[]
>Object.freeze([1, 2, 3]) : readonly number[]
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>[1, 2, 3] : number[]
>1 : 1
>2 : 2
Expand All @@ -64,9 +64,9 @@ a[0] = a[2].toString();
const o = Object.freeze({ a: 1, b: "string", c: true });
>o : Readonly<{ a: 1; b: "string"; c: true; }>
>Object.freeze({ a: 1, b: "string", c: true }) : Readonly<{ a: 1; b: "string"; c: true; }>
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object.freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: U | object; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>freeze : { <T extends Function>(f: T): T; <T extends { [idx: string]: object | U; }, U extends string | number | bigint | symbol | boolean>(o: T): Readonly<T>; <T>(o: T): Readonly<T>; }
>{ a: 1, b: "string", c: true } : { a: 1; b: "string"; c: true; }
>a : 1
>1 : 1
Expand Down
Loading