From 69acad2e893714ed5dfad8fb1194213243c3c6bf Mon Sep 17 00:00:00 2001 From: Hans Brende Date: Tue, 4 Feb 2025 14:02:27 -0600 Subject: [PATCH 1/2] Fix #61098 --- src/compiler/checker.ts | 18 +++++++ ...nditionalBrandedStringTemplateOrMapping.js | 21 ++++++++ ...onalBrandedStringTemplateOrMapping.symbols | 37 ++++++++++++++ ...tionalBrandedStringTemplateOrMapping.types | 51 +++++++++++++++++++ ...nditionalBrandedStringTemplateOrMapping.ts | 9 ++++ 5 files changed, 136 insertions(+) create mode 100644 tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.js create mode 100644 tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.symbols create mode 100644 tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.types create mode 100644 tests/cases/compiler/assignmentToConditionalBrandedStringTemplateOrMapping.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fcb93c45dc1dd..58dedf3e698b5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23003,6 +23003,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } + if (sourceFlags & TypeFlags.TemplateLiteral) { + if (arrayIsEqualTo((source as TemplateLiteralType).texts, (target as TemplateLiteralType).texts)) { + const sourceTypes = (source as TemplateLiteralType).types; + const targetTypes = (target as TemplateLiteralType).types; + result = Ternary.True; + for (let i = 0; i < sourceTypes.length; i++) { + if (!(result &= isRelatedTo(sourceTypes[i], targetTypes[i], RecursionFlags.Both, /*reportErrors*/ false))) { + break; + } + } + return result; + } + } + if (sourceFlags & TypeFlags.StringMapping) { + if ((source as StringMappingType).symbol === (target as StringMappingType).symbol) { + return isRelatedTo((source as IndexType).type, (target as IndexType).type, RecursionFlags.Both, /*reportErrors*/ false); + } + } if (!(sourceFlags & TypeFlags.Object)) { return Ternary.False; } diff --git a/tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.js b/tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.js new file mode 100644 index 0000000000000..4e6244df8e0e1 --- /dev/null +++ b/tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.js @@ -0,0 +1,21 @@ +//// [tests/cases/compiler/assignmentToConditionalBrandedStringTemplateOrMapping.ts] //// + +//// [assignmentToConditionalBrandedStringTemplateOrMapping.ts] +let a: (() => T extends `${'a' & { a: 1 }}` ? 1 : 2) = null!; +let b: (() => T extends `${'a' & { a: 1 }}` ? 1 : 2) = null!; + +a = b; + +let c: (() => T extends Uppercase<'a' & { a: 1 }> ? 1 : 2) = null!; +let d: (() => T extends Uppercase<'a' & { a: 1 }> ? 1 : 2) = null!; + +c = d; + + +//// [assignmentToConditionalBrandedStringTemplateOrMapping.js] +var a = null; +var b = null; +a = b; +var c = null; +var d = null; +c = d; diff --git a/tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.symbols b/tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.symbols new file mode 100644 index 0000000000000..250742a4b1986 --- /dev/null +++ b/tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.symbols @@ -0,0 +1,37 @@ +//// [tests/cases/compiler/assignmentToConditionalBrandedStringTemplateOrMapping.ts] //// + +=== assignmentToConditionalBrandedStringTemplateOrMapping.ts === +let a: (() => T extends `${'a' & { a: 1 }}` ? 1 : 2) = null!; +>a : Symbol(a, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 0, 3)) +>T : Symbol(T, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 0, 9)) +>T : Symbol(T, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 0, 9)) +>a : Symbol(a, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 0, 37)) + +let b: (() => T extends `${'a' & { a: 1 }}` ? 1 : 2) = null!; +>b : Symbol(b, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 1, 3)) +>T : Symbol(T, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 1, 9)) +>T : Symbol(T, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 1, 9)) +>a : Symbol(a, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 1, 37)) + +a = b; +>a : Symbol(a, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 0, 3)) +>b : Symbol(b, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 1, 3)) + +let c: (() => T extends Uppercase<'a' & { a: 1 }> ? 1 : 2) = null!; +>c : Symbol(c, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 5, 3)) +>T : Symbol(T, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 5, 9)) +>T : Symbol(T, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 5, 9)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 5, 44)) + +let d: (() => T extends Uppercase<'a' & { a: 1 }> ? 1 : 2) = null!; +>d : Symbol(d, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 6, 3)) +>T : Symbol(T, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 6, 9)) +>T : Symbol(T, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 6, 9)) +>Uppercase : Symbol(Uppercase, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 6, 44)) + +c = d; +>c : Symbol(c, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 5, 3)) +>d : Symbol(d, Decl(assignmentToConditionalBrandedStringTemplateOrMapping.ts, 6, 3)) + diff --git a/tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.types b/tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.types new file mode 100644 index 0000000000000..61dc9b88001e7 --- /dev/null +++ b/tests/baselines/reference/assignmentToConditionalBrandedStringTemplateOrMapping.types @@ -0,0 +1,51 @@ +//// [tests/cases/compiler/assignmentToConditionalBrandedStringTemplateOrMapping.ts] //// + +=== assignmentToConditionalBrandedStringTemplateOrMapping.ts === +let a: (() => T extends `${'a' & { a: 1 }}` ? 1 : 2) = null!; +>a : () => T extends `${"a" & { a: 1; }}` ? 1 : 2 +> : ^ ^^^^^^^ +>a : 1 +> : ^ +>null! : null +> : ^^^^ + +let b: (() => T extends `${'a' & { a: 1 }}` ? 1 : 2) = null!; +>b : () => T extends `${"a" & { a: 1; }}` ? 1 : 2 +> : ^ ^^^^^^^ +>a : 1 +> : ^ +>null! : null +> : ^^^^ + +a = b; +>a = b : () => T extends `${"a" & { a: 1; }}` ? 1 : 2 +> : ^ ^^^^^^^ +>a : () => T extends `${"a" & { a: 1; }}` ? 1 : 2 +> : ^ ^^^^^^^ +>b : () => T extends `${"a" & { a: 1; }}` ? 1 : 2 +> : ^ ^^^^^^^ + +let c: (() => T extends Uppercase<'a' & { a: 1 }> ? 1 : 2) = null!; +>c : () => T extends Uppercase<"a" & { a: 1; }> ? 1 : 2 +> : ^ ^^^^^^^ +>a : 1 +> : ^ +>null! : null +> : ^^^^ + +let d: (() => T extends Uppercase<'a' & { a: 1 }> ? 1 : 2) = null!; +>d : () => T extends Uppercase<"a" & { a: 1; }> ? 1 : 2 +> : ^ ^^^^^^^ +>a : 1 +> : ^ +>null! : null +> : ^^^^ + +c = d; +>c = d : () => T extends Uppercase<"a" & { a: 1; }> ? 1 : 2 +> : ^ ^^^^^^^ +>c : () => T extends Uppercase<"a" & { a: 1; }> ? 1 : 2 +> : ^ ^^^^^^^ +>d : () => T extends Uppercase<"a" & { a: 1; }> ? 1 : 2 +> : ^ ^^^^^^^ + diff --git a/tests/cases/compiler/assignmentToConditionalBrandedStringTemplateOrMapping.ts b/tests/cases/compiler/assignmentToConditionalBrandedStringTemplateOrMapping.ts new file mode 100644 index 0000000000000..475e42e2f138b --- /dev/null +++ b/tests/cases/compiler/assignmentToConditionalBrandedStringTemplateOrMapping.ts @@ -0,0 +1,9 @@ +let a: (() => T extends `${'a' & { a: 1 }}` ? 1 : 2) = null!; +let b: (() => T extends `${'a' & { a: 1 }}` ? 1 : 2) = null!; + +a = b; + +let c: (() => T extends Uppercase<'a' & { a: 1 }> ? 1 : 2) = null!; +let d: (() => T extends Uppercase<'a' & { a: 1 }> ? 1 : 2) = null!; + +c = d; From ab62dc556a322180b6da8fd6648b5a037b9b49b5 Mon Sep 17 00:00:00 2001 From: Hans Brende Date: Tue, 4 Feb 2025 14:48:02 -0600 Subject: [PATCH 2/2] fix typo --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 58dedf3e698b5..c10bec95be42d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -23018,7 +23018,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (sourceFlags & TypeFlags.StringMapping) { if ((source as StringMappingType).symbol === (target as StringMappingType).symbol) { - return isRelatedTo((source as IndexType).type, (target as IndexType).type, RecursionFlags.Both, /*reportErrors*/ false); + return isRelatedTo((source as StringMappingType).type, (target as StringMappingType).type, RecursionFlags.Both, /*reportErrors*/ false); } } if (!(sourceFlags & TypeFlags.Object)) {