Skip to content

Commit 94564cf

Browse files
authored
Type with diverging read/write normalizations still identical to itself (microsoft#54033)
1 parent ae6393e commit 94564cf

File tree

4 files changed

+209
-0
lines changed

4 files changed

+209
-0
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20612,6 +20612,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2061220612
* * Ternary.False if they are not related.
2061320613
*/
2061420614
function isRelatedTo(originalSource: Type, originalTarget: Type, recursionFlags: RecursionFlags = RecursionFlags.Both, reportErrors = false, headMessage?: DiagnosticMessage, intersectionState = IntersectionState.None): Ternary {
20615+
if (originalSource === originalTarget) return Ternary.True;
20616+
2061520617
// Before normalization: if `source` is type an object type, and `target` is primitive,
2061620618
// skip all the checks we don't need and just return `isSimpleTypeRelatedTo` result
2061720619
if (originalSource.flags & TypeFlags.Object && originalTarget.flags & TypeFlags.Primitive) {
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
=== tests/cases/compiler/identityAndDivergentNormalizedTypes.ts ===
2+
// Repros from #53998
3+
4+
type ApiPost =
5+
>ApiPost : Symbol(ApiPost, Decl(identityAndDivergentNormalizedTypes.ts, 0, 0))
6+
7+
| {
8+
path: "/login";
9+
>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 3, 7))
10+
11+
body: {};
12+
>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 4, 23))
13+
}
14+
| {
15+
path: "/user";
16+
>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 7, 7))
17+
18+
body: { name: string; };
19+
>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 8, 22))
20+
>name : Symbol(name, Decl(identityAndDivergentNormalizedTypes.ts, 9, 15))
21+
}
22+
23+
type PostPath = ApiPost["path"];
24+
>PostPath : Symbol(PostPath, Decl(identityAndDivergentNormalizedTypes.ts, 10, 5))
25+
>ApiPost : Symbol(ApiPost, Decl(identityAndDivergentNormalizedTypes.ts, 0, 0))
26+
27+
type PostBody<PATH extends PostPath> = Extract<ApiPost, { path: PATH }>["body"];
28+
>PostBody : Symbol(PostBody, Decl(identityAndDivergentNormalizedTypes.ts, 12, 32))
29+
>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 14, 14))
30+
>PostPath : Symbol(PostPath, Decl(identityAndDivergentNormalizedTypes.ts, 10, 5))
31+
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
32+
>ApiPost : Symbol(ApiPost, Decl(identityAndDivergentNormalizedTypes.ts, 0, 0))
33+
>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 14, 57))
34+
>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 14, 14))
35+
36+
const post = <PATH extends PostPath>(
37+
>post : Symbol(post, Decl(identityAndDivergentNormalizedTypes.ts, 16, 5))
38+
>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 16, 14))
39+
>PostPath : Symbol(PostPath, Decl(identityAndDivergentNormalizedTypes.ts, 10, 5))
40+
41+
path: PATH,
42+
>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 16, 37))
43+
>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 16, 14))
44+
45+
{body, ...options}: Omit<RequestInit, 'body'> & {body: PostBody<PATH>}
46+
>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 18, 5))
47+
>options : Symbol(options, Decl(identityAndDivergentNormalizedTypes.ts, 18, 10))
48+
>Omit : Symbol(Omit, Decl(lib.es5.d.ts, --, --))
49+
>RequestInit : Symbol(RequestInit, Decl(lib.dom.d.ts, --, --))
50+
>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 18, 53))
51+
>PostBody : Symbol(PostBody, Decl(identityAndDivergentNormalizedTypes.ts, 12, 32))
52+
>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 16, 14))
53+
54+
) => {
55+
}
56+
57+
const tmp = <PATH extends PostPath>(
58+
>tmp : Symbol(tmp, Decl(identityAndDivergentNormalizedTypes.ts, 22, 5))
59+
>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 22, 13))
60+
>PostPath : Symbol(PostPath, Decl(identityAndDivergentNormalizedTypes.ts, 10, 5))
61+
62+
path: PATH,
63+
>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 22, 36))
64+
>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 22, 13))
65+
66+
body: PostBody<PATH>
67+
>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 23, 13))
68+
>PostBody : Symbol(PostBody, Decl(identityAndDivergentNormalizedTypes.ts, 12, 32))
69+
>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 22, 13))
70+
71+
) => {
72+
post<PATH>(path, { body })
73+
>post : Symbol(post, Decl(identityAndDivergentNormalizedTypes.ts, 16, 5))
74+
>PATH : Symbol(PATH, Decl(identityAndDivergentNormalizedTypes.ts, 22, 13))
75+
>path : Symbol(path, Decl(identityAndDivergentNormalizedTypes.ts, 22, 36))
76+
>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 26, 20))
77+
}
78+
79+
function fx1<P extends PostPath>(x: { body: PostBody<P> }, y: { body: PostBody<P> }) {
80+
>fx1 : Symbol(fx1, Decl(identityAndDivergentNormalizedTypes.ts, 27, 1))
81+
>P : Symbol(P, Decl(identityAndDivergentNormalizedTypes.ts, 29, 13))
82+
>PostPath : Symbol(PostPath, Decl(identityAndDivergentNormalizedTypes.ts, 10, 5))
83+
>x : Symbol(x, Decl(identityAndDivergentNormalizedTypes.ts, 29, 33))
84+
>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 29, 37))
85+
>PostBody : Symbol(PostBody, Decl(identityAndDivergentNormalizedTypes.ts, 12, 32))
86+
>P : Symbol(P, Decl(identityAndDivergentNormalizedTypes.ts, 29, 13))
87+
>y : Symbol(y, Decl(identityAndDivergentNormalizedTypes.ts, 29, 58))
88+
>body : Symbol(body, Decl(identityAndDivergentNormalizedTypes.ts, 29, 63))
89+
>PostBody : Symbol(PostBody, Decl(identityAndDivergentNormalizedTypes.ts, 12, 32))
90+
>P : Symbol(P, Decl(identityAndDivergentNormalizedTypes.ts, 29, 13))
91+
92+
x = y;
93+
>x : Symbol(x, Decl(identityAndDivergentNormalizedTypes.ts, 29, 33))
94+
>y : Symbol(y, Decl(identityAndDivergentNormalizedTypes.ts, 29, 58))
95+
}
96+
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
=== tests/cases/compiler/identityAndDivergentNormalizedTypes.ts ===
2+
// Repros from #53998
3+
4+
type ApiPost =
5+
>ApiPost : { path: "/login"; body: {}; } | { path: "/user"; body: { name: string;}; }
6+
7+
| {
8+
path: "/login";
9+
>path : "/login"
10+
11+
body: {};
12+
>body : {}
13+
}
14+
| {
15+
path: "/user";
16+
>path : "/user"
17+
18+
body: { name: string; };
19+
>body : { name: string; }
20+
>name : string
21+
}
22+
23+
type PostPath = ApiPost["path"];
24+
>PostPath : "/login" | "/user"
25+
26+
type PostBody<PATH extends PostPath> = Extract<ApiPost, { path: PATH }>["body"];
27+
>PostBody : PostBody<PATH>
28+
>path : PATH
29+
30+
const post = <PATH extends PostPath>(
31+
>post : <PATH extends "/login" | "/user">(path: PATH, { body, ...options }: Omit<RequestInit, "body"> & { body: PostBody<PATH>; }) => void
32+
><PATH extends PostPath>( path: PATH, {body, ...options}: Omit<RequestInit, 'body'> & {body: PostBody<PATH>}) => {} : <PATH extends "/login" | "/user">(path: PATH, { body, ...options }: Omit<RequestInit, "body"> & { body: PostBody<PATH>; }) => void
33+
34+
path: PATH,
35+
>path : PATH
36+
37+
{body, ...options}: Omit<RequestInit, 'body'> & {body: PostBody<PATH>}
38+
>body : PostBody<PATH>
39+
>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; }
40+
>body : PostBody<PATH>
41+
42+
) => {
43+
}
44+
45+
const tmp = <PATH extends PostPath>(
46+
>tmp : <PATH extends "/login" | "/user">(path: PATH, body: PostBody<PATH>) => void
47+
><PATH extends PostPath>( path: PATH, body: PostBody<PATH>) => { post<PATH>(path, { body })} : <PATH extends "/login" | "/user">(path: PATH, body: PostBody<PATH>) => void
48+
49+
path: PATH,
50+
>path : PATH
51+
52+
body: PostBody<PATH>
53+
>body : PostBody<PATH>
54+
55+
) => {
56+
post<PATH>(path, { body })
57+
>post<PATH>(path, { body }) : void
58+
>post : <PATH extends "/login" | "/user">(path: PATH, { body, ...options }: Omit<RequestInit, "body"> & { body: PostBody<PATH>; }) => void
59+
>path : PATH
60+
>{ body } : { body: PostBody<PATH>; }
61+
>body : PostBody<PATH>
62+
}
63+
64+
function fx1<P extends PostPath>(x: { body: PostBody<P> }, y: { body: PostBody<P> }) {
65+
>fx1 : <P extends "/login" | "/user">(x: { body: PostBody<P>;}, y: { body: PostBody<P>;}) => void
66+
>x : { body: PostBody<P>; }
67+
>body : PostBody<P>
68+
>y : { body: PostBody<P>; }
69+
>body : PostBody<P>
70+
71+
x = y;
72+
>x = y : { body: PostBody<P>; }
73+
>x : { body: PostBody<P>; }
74+
>y : { body: PostBody<P>; }
75+
}
76+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// Repros from #53998
5+
6+
type ApiPost =
7+
| {
8+
path: "/login";
9+
body: {};
10+
}
11+
| {
12+
path: "/user";
13+
body: { name: string; };
14+
}
15+
16+
type PostPath = ApiPost["path"];
17+
18+
type PostBody<PATH extends PostPath> = Extract<ApiPost, { path: PATH }>["body"];
19+
20+
const post = <PATH extends PostPath>(
21+
path: PATH,
22+
{body, ...options}: Omit<RequestInit, 'body'> & {body: PostBody<PATH>}
23+
) => {
24+
}
25+
26+
const tmp = <PATH extends PostPath>(
27+
path: PATH,
28+
body: PostBody<PATH>
29+
) => {
30+
post<PATH>(path, { body })
31+
}
32+
33+
function fx1<P extends PostPath>(x: { body: PostBody<P> }, y: { body: PostBody<P> }) {
34+
x = y;
35+
}

0 commit comments

Comments
 (0)