diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7f56a22bdc501..ad90bde210f0b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10458,7 +10458,7 @@ namespace ts { append(propTypes, getIndexTypeOfType(type, IndexKind.Number)); } if (propTypes.length) { - return getUnionType(propTypes, UnionReduction.Subtype); + return getUnionType(propTypes); } } return undefined; diff --git a/tests/baselines/reference/inferrenceInfiniteLoopWithSubtyping.js b/tests/baselines/reference/inferrenceInfiniteLoopWithSubtyping.js new file mode 100644 index 0000000000000..0a58f83cdbc2b --- /dev/null +++ b/tests/baselines/reference/inferrenceInfiniteLoopWithSubtyping.js @@ -0,0 +1,49 @@ +//// [tests/cases/compiler/inferrenceInfiniteLoopWithSubtyping.ts] //// + +//// [graphql-compose.d.ts] +export type ObjMapReadOnly = Readonly<{ [key: string]: Readonly }>; +export type Thunk = (() => T) | T; + +export type ComposeOutputTypeDefinition = Readonly | EnumTypeComposer>; + +export class EnumTypeComposer { + public setFields(fields: { [name: string]: { [key: string]: any } }): this; +} + +export class ObjectTypeComposer { + public setFields(fields: ObjMapReadOnly): this; + + public addResolver(opts: { type?: Thunk }): this; +} + +export class Resolver { + public wrapArgs( + cb: () => { + [argName: string]: Thunk>; + } + ): void; + + public wrapType(cb: () => ComposeOutputTypeDefinition): void; +} + + +//// [app.ts] +import { ObjectTypeComposer } from './graphql-compose'; + +declare const User: ObjectTypeComposer; + +User.addResolver({ + type: User, // `User as any` fix the problem +}); + + +//// [app.js] +"use strict"; +exports.__esModule = true; +User.addResolver({ + type: User +}); + + +//// [app.d.ts] +export {}; diff --git a/tests/baselines/reference/inferrenceInfiniteLoopWithSubtyping.symbols b/tests/baselines/reference/inferrenceInfiniteLoopWithSubtyping.symbols new file mode 100644 index 0000000000000..22e88c9f6e8df --- /dev/null +++ b/tests/baselines/reference/inferrenceInfiniteLoopWithSubtyping.symbols @@ -0,0 +1,95 @@ +=== tests/cases/compiler/graphql-compose.d.ts === +export type ObjMapReadOnly = Readonly<{ [key: string]: Readonly }>; +>ObjMapReadOnly : Symbol(ObjMapReadOnly, Decl(graphql-compose.d.ts, 0, 0)) +>T : Symbol(T, Decl(graphql-compose.d.ts, 0, 27)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>key : Symbol(key, Decl(graphql-compose.d.ts, 0, 44)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(graphql-compose.d.ts, 0, 27)) + +export type Thunk = (() => T) | T; +>Thunk : Symbol(Thunk, Decl(graphql-compose.d.ts, 0, 73)) +>T : Symbol(T, Decl(graphql-compose.d.ts, 1, 18)) +>T : Symbol(T, Decl(graphql-compose.d.ts, 1, 18)) +>T : Symbol(T, Decl(graphql-compose.d.ts, 1, 18)) + +export type ComposeOutputTypeDefinition = Readonly | EnumTypeComposer>; +>ComposeOutputTypeDefinition : Symbol(ComposeOutputTypeDefinition, Decl(graphql-compose.d.ts, 1, 37)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>ObjectTypeComposer : Symbol(ObjectTypeComposer, Decl(graphql-compose.d.ts, 7, 1)) +>EnumTypeComposer : Symbol(EnumTypeComposer, Decl(graphql-compose.d.ts, 3, 100)) + +export class EnumTypeComposer { +>EnumTypeComposer : Symbol(EnumTypeComposer, Decl(graphql-compose.d.ts, 3, 100)) + + public setFields(fields: { [name: string]: { [key: string]: any } }): this; +>setFields : Symbol(EnumTypeComposer.setFields, Decl(graphql-compose.d.ts, 5, 31)) +>fields : Symbol(fields, Decl(graphql-compose.d.ts, 6, 19)) +>name : Symbol(name, Decl(graphql-compose.d.ts, 6, 30)) +>key : Symbol(key, Decl(graphql-compose.d.ts, 6, 48)) +} + +export class ObjectTypeComposer { +>ObjectTypeComposer : Symbol(ObjectTypeComposer, Decl(graphql-compose.d.ts, 7, 1)) +>TSource : Symbol(TSource, Decl(graphql-compose.d.ts, 9, 32)) +>TContext : Symbol(TContext, Decl(graphql-compose.d.ts, 9, 40)) + + public setFields(fields: ObjMapReadOnly): this; +>setFields : Symbol(ObjectTypeComposer.setFields, Decl(graphql-compose.d.ts, 9, 52)) +>fields : Symbol(fields, Decl(graphql-compose.d.ts, 10, 19)) +>ObjMapReadOnly : Symbol(ObjMapReadOnly, Decl(graphql-compose.d.ts, 0, 0)) +>Resolver : Symbol(Resolver, Decl(graphql-compose.d.ts, 13, 1)) + + public addResolver(opts: { type?: Thunk }): this; +>addResolver : Symbol(ObjectTypeComposer.addResolver, Decl(graphql-compose.d.ts, 10, 59)) +>TResolverSource : Symbol(TResolverSource, Decl(graphql-compose.d.ts, 12, 21)) +>opts : Symbol(opts, Decl(graphql-compose.d.ts, 12, 38)) +>type : Symbol(type, Decl(graphql-compose.d.ts, 12, 45)) +>Thunk : Symbol(Thunk, Decl(graphql-compose.d.ts, 0, 73)) +>ComposeOutputTypeDefinition : Symbol(ComposeOutputTypeDefinition, Decl(graphql-compose.d.ts, 1, 37)) +} + +export class Resolver { +>Resolver : Symbol(Resolver, Decl(graphql-compose.d.ts, 13, 1)) + + public wrapArgs( +>wrapArgs : Symbol(Resolver.wrapArgs, Decl(graphql-compose.d.ts, 15, 23)) +>NewContext : Symbol(NewContext, Decl(graphql-compose.d.ts, 16, 18)) + + cb: () => { +>cb : Symbol(cb, Decl(graphql-compose.d.ts, 16, 30)) + + [argName: string]: Thunk>; +>argName : Symbol(argName, Decl(graphql-compose.d.ts, 18, 7)) +>Thunk : Symbol(Thunk, Decl(graphql-compose.d.ts, 0, 73)) +>Readonly : Symbol(Readonly, Decl(lib.es5.d.ts, --, --)) +>EnumTypeComposer : Symbol(EnumTypeComposer, Decl(graphql-compose.d.ts, 3, 100)) + } + ): void; + + public wrapType(cb: () => ComposeOutputTypeDefinition): void; +>wrapType : Symbol(Resolver.wrapType, Decl(graphql-compose.d.ts, 20, 10)) +>cb : Symbol(cb, Decl(graphql-compose.d.ts, 22, 18)) +>ComposeOutputTypeDefinition : Symbol(ComposeOutputTypeDefinition, Decl(graphql-compose.d.ts, 1, 37)) +} + + +=== tests/cases/compiler/app.ts === +import { ObjectTypeComposer } from './graphql-compose'; +>ObjectTypeComposer : Symbol(ObjectTypeComposer, Decl(app.ts, 0, 8)) + +declare const User: ObjectTypeComposer; +>User : Symbol(User, Decl(app.ts, 2, 13)) +>ObjectTypeComposer : Symbol(ObjectTypeComposer, Decl(app.ts, 0, 8)) + +User.addResolver({ +>User.addResolver : Symbol(ObjectTypeComposer.addResolver, Decl(graphql-compose.d.ts, 10, 59)) +>User : Symbol(User, Decl(app.ts, 2, 13)) +>addResolver : Symbol(ObjectTypeComposer.addResolver, Decl(graphql-compose.d.ts, 10, 59)) + + type: User, // `User as any` fix the problem +>type : Symbol(type, Decl(app.ts, 4, 18)) +>User : Symbol(User, Decl(app.ts, 2, 13)) + +}); + diff --git a/tests/baselines/reference/inferrenceInfiniteLoopWithSubtyping.types b/tests/baselines/reference/inferrenceInfiniteLoopWithSubtyping.types new file mode 100644 index 0000000000000..6b0ddd64b3bf5 --- /dev/null +++ b/tests/baselines/reference/inferrenceInfiniteLoopWithSubtyping.types @@ -0,0 +1,74 @@ +=== tests/cases/compiler/graphql-compose.d.ts === +export type ObjMapReadOnly = Readonly<{ [key: string]: Readonly }>; +>ObjMapReadOnly : Readonly<{ [key: string]: Readonly; }> +>key : string + +export type Thunk = (() => T) | T; +>Thunk : Thunk + +export type ComposeOutputTypeDefinition = Readonly | EnumTypeComposer>; +>ComposeOutputTypeDefinition : Readonly> | Readonly + +export class EnumTypeComposer { +>EnumTypeComposer : EnumTypeComposer + + public setFields(fields: { [name: string]: { [key: string]: any } }): this; +>setFields : (fields: { [name: string]: { [key: string]: any; }; }) => this +>fields : { [name: string]: { [key: string]: any; }; } +>name : string +>key : string +} + +export class ObjectTypeComposer { +>ObjectTypeComposer : ObjectTypeComposer + + public setFields(fields: ObjMapReadOnly): this; +>setFields : (fields: Readonly<{ [key: string]: Readonly; }>) => this +>fields : Readonly<{ [key: string]: Readonly; }> + + public addResolver(opts: { type?: Thunk }): this; +>addResolver : (opts: { type?: Thunk> | Readonly>; }) => this +>opts : { type?: Thunk> | Readonly>; } +>type : Thunk> | Readonly> +} + +export class Resolver { +>Resolver : Resolver + + public wrapArgs( +>wrapArgs : (cb: () => { [argName: string]: Thunk>; }) => void + + cb: () => { +>cb : () => { [argName: string]: Thunk>; } + + [argName: string]: Thunk>; +>argName : string + } + ): void; + + public wrapType(cb: () => ComposeOutputTypeDefinition): void; +>wrapType : (cb: () => Readonly> | Readonly) => void +>cb : () => Readonly> | Readonly +} + + +=== tests/cases/compiler/app.ts === +import { ObjectTypeComposer } from './graphql-compose'; +>ObjectTypeComposer : typeof ObjectTypeComposer + +declare const User: ObjectTypeComposer; +>User : ObjectTypeComposer + +User.addResolver({ +>User.addResolver({ type: User, // `User as any` fix the problem}) : ObjectTypeComposer +>User.addResolver : (opts: { type?: import("tests/cases/compiler/graphql-compose").Thunk> | Readonly>; }) => ObjectTypeComposer +>User : ObjectTypeComposer +>addResolver : (opts: { type?: import("tests/cases/compiler/graphql-compose").Thunk> | Readonly>; }) => ObjectTypeComposer +>{ type: User, // `User as any` fix the problem} : { type: ObjectTypeComposer; } + + type: User, // `User as any` fix the problem +>type : ObjectTypeComposer +>User : ObjectTypeComposer + +}); + diff --git a/tests/cases/compiler/inferrenceInfiniteLoopWithSubtyping.ts b/tests/cases/compiler/inferrenceInfiniteLoopWithSubtyping.ts new file mode 100644 index 0000000000000..b08ac6ab39b82 --- /dev/null +++ b/tests/cases/compiler/inferrenceInfiniteLoopWithSubtyping.ts @@ -0,0 +1,36 @@ +// @filename: graphql-compose.d.ts +// @declaration: true +export type ObjMapReadOnly = Readonly<{ [key: string]: Readonly }>; +export type Thunk = (() => T) | T; + +export type ComposeOutputTypeDefinition = Readonly | EnumTypeComposer>; + +export class EnumTypeComposer { + public setFields(fields: { [name: string]: { [key: string]: any } }): this; +} + +export class ObjectTypeComposer { + public setFields(fields: ObjMapReadOnly): this; + + public addResolver(opts: { type?: Thunk }): this; +} + +export class Resolver { + public wrapArgs( + cb: () => { + [argName: string]: Thunk>; + } + ): void; + + public wrapType(cb: () => ComposeOutputTypeDefinition): void; +} + + +// @filename: app.ts +import { ObjectTypeComposer } from './graphql-compose'; + +declare const User: ObjectTypeComposer; + +User.addResolver({ + type: User, // `User as any` fix the problem +});