diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4bd79b9d7a2..1bb5c6a2977 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20612,6 +20612,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * * Ternary.False if they are not related. */ function isRelatedTo(originalSource: Type, originalTarget: Type, recursionFlags: RecursionFlags = RecursionFlags.Both, reportErrors = false, headMessage?: DiagnosticMessage, intersectionState = IntersectionState.None): Ternary { + if (originalSource === originalTarget) return Ternary.True; + // Before normalization: if `source` is type an object type, and `target` is primitive, // skip all the checks we don't need and just return `isSimpleTypeRelatedTo` result if (originalSource.flags & TypeFlags.Object && originalTarget.flags & TypeFlags.Primitive) { diff --git a/tests/baselines/reference/identityAndDivergentNormalizedTypes.symbols b/tests/baselines/reference/identityAndDivergentNormalizedTypes.symbols new file mode 100644 index 00000000000..b65ab20b3a4 --- /dev/null +++ b/tests/baselines/reference/identityAndDivergentNormalizedTypes.symbols @@ -0,0 +1,96 @@ +=== tests/cases/compiler/identityAndDivergentNormalizedTypes.ts === +// Repros from #53998 + +type ApiPost = +>ApiPost : Symbol(ApiPost, Decl(identityAndDivergentNormalizedTypes.ts, 0, 0)) + + | { + path: "/login"; +>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 3, 7)) + + body: {}; +>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 4, 23)) + } + | { + path: "/user"; +>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 7, 7)) + + body: { name: string; }; +>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 8, 22)) +>name : Symbol(name, Decl(identityAndDivergentNormalizedTypes.ts, 9, 15)) + } + +type PostPath = ApiPost["path"]; +>PostPath : Symbol(PostPath, Decl(identityAndDivergentNormalizedTypes.ts, 10, 5)) +>ApiPost : Symbol(ApiPost, Decl(identityAndDivergentNormalizedTypes.ts, 0, 0)) + +type PostBody = Extract["body"]; +>PostBody : Symbol(PostBody, Decl(identityAndDivergentNormalizedTypes.ts, 12, 32)) +>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 14, 14)) +>PostPath : Symbol(PostPath, Decl(identityAndDivergentNormalizedTypes.ts, 10, 5)) +>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) +>ApiPost : Symbol(ApiPost, Decl(identityAndDivergentNormalizedTypes.ts, 0, 0)) +>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 14, 57)) +>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 14, 14)) + +const post = ( +>post : Symbol(post, Decl(identityAndDivergentNormalizedTypes.ts, 16, 5)) +>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 16, 14)) +>PostPath : Symbol(PostPath, Decl(identityAndDivergentNormalizedTypes.ts, 10, 5)) + + path: PATH, +>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 16, 37)) +>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 16, 14)) + + {body, ...options}: Omit & {body: PostBody} +>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 18, 5)) +>options : Symbol(options, Decl(identityAndDivergentNormalizedTypes.ts, 18, 10)) +>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --)) +>RequestInit : Symbol(RequestInit, Decl(lib.dom.d.ts, --, --)) +>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 18, 53)) +>PostBody : Symbol(PostBody, Decl(identityAndDivergentNormalizedTypes.ts, 12, 32)) +>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 16, 14)) + +) => { +} + +const tmp = ( +>tmp : Symbol(tmp, Decl(identityAndDivergentNormalizedTypes.ts, 22, 5)) +>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 22, 13)) +>PostPath : Symbol(PostPath, Decl(identityAndDivergentNormalizedTypes.ts, 10, 5)) + + path: PATH, +>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 22, 36)) +>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 22, 13)) + + body: PostBody +>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 23, 13)) +>PostBody : Symbol(PostBody, Decl(identityAndDivergentNormalizedTypes.ts, 12, 32)) +>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 22, 13)) + +) => { + post(path, { body }) +>post : Symbol(post, Decl(identityAndDivergentNormalizedTypes.ts, 16, 5)) +>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 22, 13)) +>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 22, 36)) +>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 26, 20)) +} + +function fx1

(x: { body: PostBody

}, y: { body: PostBody

}) { +>fx1 : Symbol(fx1, Decl(identityAndDivergentNormalizedTypes.ts, 27, 1)) +>P : Symbol(P, Decl(identityAndDivergentNormalizedTypes.ts, 29, 13)) +>PostPath : Symbol(PostPath, Decl(identityAndDivergentNormalizedTypes.ts, 10, 5)) +>x : Symbol(x, Decl(identityAndDivergentNormalizedTypes.ts, 29, 33)) +>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 29, 37)) +>PostBody : Symbol(PostBody, Decl(identityAndDivergentNormalizedTypes.ts, 12, 32)) +>P : Symbol(P, Decl(identityAndDivergentNormalizedTypes.ts, 29, 13)) +>y : Symbol(y, Decl(identityAndDivergentNormalizedTypes.ts, 29, 58)) +>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 29, 63)) +>PostBody : Symbol(PostBody, Decl(identityAndDivergentNormalizedTypes.ts, 12, 32)) +>P : Symbol(P, Decl(identityAndDivergentNormalizedTypes.ts, 29, 13)) + + x = y; +>x : Symbol(x, Decl(identityAndDivergentNormalizedTypes.ts, 29, 33)) +>y : Symbol(y, Decl(identityAndDivergentNormalizedTypes.ts, 29, 58)) +} + diff --git a/tests/baselines/reference/identityAndDivergentNormalizedTypes.types b/tests/baselines/reference/identityAndDivergentNormalizedTypes.types new file mode 100644 index 00000000000..15dff40bd92 --- /dev/null +++ b/tests/baselines/reference/identityAndDivergentNormalizedTypes.types @@ -0,0 +1,76 @@ +=== tests/cases/compiler/identityAndDivergentNormalizedTypes.ts === +// Repros from #53998 + +type ApiPost = +>ApiPost : { path: "/login"; body: {}; } | { path: "/user"; body: { name: string;}; } + + | { + path: "/login"; +>path : "/login" + + body: {}; +>body : {} + } + | { + path: "/user"; +>path : "/user" + + body: { name: string; }; +>body : { name: string; } +>name : string + } + +type PostPath = ApiPost["path"]; +>PostPath : "/login" | "/user" + +type PostBody = Extract["body"]; +>PostBody : PostBody +>path : PATH + +const post = ( +>post : (path: PATH, { body, ...options }: Omit & { body: PostBody; }) => void +>( path: PATH, {body, ...options}: Omit & {body: PostBody}) => {} : (path: PATH, { body, ...options }: Omit & { body: PostBody; }) => void + + path: PATH, +>path : PATH + + {body, ...options}: Omit & {body: PostBody} +>body : PostBody +>options : { cache?: RequestCache | undefined; credentials?: RequestCredentials | undefined; headers?: HeadersInit | undefined; integrity?: string | undefined; keepalive?: boolean | undefined; method?: string | undefined; mode?: RequestMode | undefined; redirect?: RequestRedirect | undefined; referrer?: string | undefined; referrerPolicy?: ReferrerPolicy | undefined; signal?: AbortSignal | null | undefined; window?: null | undefined; } +>body : PostBody + +) => { +} + +const tmp = ( +>tmp : (path: PATH, body: PostBody) => void +>( path: PATH, body: PostBody) => { post(path, { body })} : (path: PATH, body: PostBody) => void + + path: PATH, +>path : PATH + + body: PostBody +>body : PostBody + +) => { + post(path, { body }) +>post(path, { body }) : void +>post : (path: PATH, { body, ...options }: Omit & { body: PostBody; }) => void +>path : PATH +>{ body } : { body: PostBody; } +>body : PostBody +} + +function fx1

(x: { body: PostBody

}, y: { body: PostBody

}) { +>fx1 :

(x: { body: PostBody

;}, y: { body: PostBody

;}) => void +>x : { body: PostBody

; } +>body : PostBody

+>y : { body: PostBody

; } +>body : PostBody

+ + x = y; +>x = y : { body: PostBody

; } +>x : { body: PostBody

; } +>y : { body: PostBody

; } +} + diff --git a/tests/cases/compiler/identityAndDivergentNormalizedTypes.ts b/tests/cases/compiler/identityAndDivergentNormalizedTypes.ts new file mode 100644 index 00000000000..dc0059ef263 --- /dev/null +++ b/tests/cases/compiler/identityAndDivergentNormalizedTypes.ts @@ -0,0 +1,35 @@ +// @strict: true +// @noEmit: true + +// Repros from #53998 + +type ApiPost = + | { + path: "/login"; + body: {}; + } + | { + path: "/user"; + body: { name: string; }; + } + +type PostPath = ApiPost["path"]; + +type PostBody = Extract["body"]; + +const post = ( + path: PATH, + {body, ...options}: Omit & {body: PostBody} +) => { +} + +const tmp = ( + path: PATH, + body: PostBody +) => { + post(path, { body }) +} + +function fx1

(x: { body: PostBody

}, y: { body: PostBody

}) { + x = y; +}