@@ -1152,6 +1152,29 @@ func (c *Checker) findMatchingTemplateLiteralInTrie(trie *templateLiteralTrieNod
11521152 return nil
11531153}
11541154
1155+ func (c * Checker ) buildTemplateLiteralTrie (unionType * Type ) * templateLiteralTrieNode {
1156+ types := unionType .Types ()
1157+ var templateTypes []* Type
1158+ for _ , t := range types {
1159+ if t .flags & TypeFlagsTemplateLiteral != 0 {
1160+ templateTypes = append (templateTypes , t )
1161+ }
1162+ }
1163+ if len (templateTypes ) < 5 {
1164+ return nil
1165+ }
1166+ return c .buildTemplateLiteralTrieFromTypes (templateTypes )
1167+ }
1168+
1169+ func (c * Checker ) getTemplateLiteralTrie (unionType * Type ) * templateLiteralTrieNode {
1170+ u := unionType .AsUnionType ()
1171+ if ! u .templateLiteralTrieComputed {
1172+ u .templateLiteralTrie = c .buildTemplateLiteralTrie (unionType )
1173+ u .templateLiteralTrieComputed = true
1174+ }
1175+ return u .templateLiteralTrie
1176+ }
1177+
11551178// Return the name of a discriminant property for which it was possible and feasible to construct a map of
11561179// constituent types keyed by the literal types of the property by that name in each constituent type. Return
11571180// an empty string if no such discriminant property exists.
@@ -3013,6 +3036,36 @@ func (r *Relater) typeRelatedToSomeType(source *Type, target *Type, reportErrors
30133036 }
30143037 }
30153038 }
3039+ // Fast path: trie-based lookup for string literal source against unions with template literals
3040+ if source .flags & TypeFlagsStringLiteral != 0 {
3041+ trie := r .c .getTemplateLiteralTrie (target )
3042+ if trie != nil {
3043+ trieMatch := r .c .findMatchingTemplateLiteralInTrie (trie , source , r .isRelatedToWorker )
3044+ if trieMatch != nil {
3045+ related := r .isRelatedToEx (source , trieMatch , RecursionFlagsTarget , false /*reportErrors*/ , nil /*headMessage*/ , intersectionState )
3046+ if related != TernaryFalse {
3047+ return related
3048+ }
3049+ }
3050+ // Trie covered all template literals; containsType covered all string literals.
3051+ // Check remaining non-literal, non-template members.
3052+ for _ , t := range targetTypes {
3053+ if t .flags & (TypeFlagsStringLiteral | TypeFlagsTemplateLiteral ) == 0 {
3054+ related := r .isRelatedToEx (source , t , RecursionFlagsTarget , false /*reportErrors*/ , nil /*headMessage*/ , intersectionState )
3055+ if related != TernaryFalse {
3056+ return related
3057+ }
3058+ }
3059+ }
3060+ if reportErrors {
3061+ bestMatchingType := r .c .getBestMatchingType (source , target , r .isRelatedToSimple )
3062+ if bestMatchingType != nil {
3063+ r .isRelatedToEx (source , bestMatchingType , RecursionFlagsTarget , true /*reportErrors*/ , nil /*headMessage*/ , intersectionState )
3064+ }
3065+ }
3066+ return TernaryFalse
3067+ }
3068+ }
30163069 for _ , t := range targetTypes {
30173070 related := r .isRelatedToEx (source , t , RecursionFlagsTarget , false /*reportErrors*/ , nil /*headMessage*/ , intersectionState )
30183071 if related != TernaryFalse {
0 commit comments