@@ -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.
@@ -3012,6 +3035,36 @@ func (r *Relater) typeRelatedToSomeType(source *Type, target *Type, reportErrors
30123035 return related
30133036 }
30143037 }
3038+ // Fast path: trie-based lookup for string literal source against unions with template literals
3039+ if source .flags & TypeFlagsStringLiteral != 0 {
3040+ trie := r .c .getTemplateLiteralTrie (target )
3041+ if trie != nil {
3042+ trieMatch := r .c .findMatchingTemplateLiteralInTrie (trie , source , r .isRelatedToWorker )
3043+ if trieMatch != nil {
3044+ related := r .isRelatedToEx (source , trieMatch , RecursionFlagsTarget , false /*reportErrors*/ , nil /*headMessage*/ , intersectionState )
3045+ if related != TernaryFalse {
3046+ return related
3047+ }
3048+ }
3049+ // Trie covered all template literals; containsType covered all string literals.
3050+ // Check remaining non-literal, non-template members.
3051+ for _ , t := range targetTypes {
3052+ if t .flags & (TypeFlagsStringLiteral | TypeFlagsTemplateLiteral ) == 0 {
3053+ related := r .isRelatedToEx (source , t , RecursionFlagsTarget , false /*reportErrors*/ , nil /*headMessage*/ , intersectionState )
3054+ if related != TernaryFalse {
3055+ return related
3056+ }
3057+ }
3058+ }
3059+ if reportErrors {
3060+ bestMatchingType := r .c .getBestMatchingType (source , target , r .isRelatedToSimple )
3061+ if bestMatchingType != nil {
3062+ r .isRelatedToEx (source , bestMatchingType , RecursionFlagsTarget , true /*reportErrors*/ , nil /*headMessage*/ , intersectionState )
3063+ }
3064+ }
3065+ return TernaryFalse
3066+ }
3067+ }
30153068 }
30163069 for _ , t := range targetTypes {
30173070 related := r .isRelatedToEx (source , t , RecursionFlagsTarget , false /*reportErrors*/ , nil /*headMessage*/ , intersectionState )
0 commit comments