(t *Type, candidate *Type, assumeTrue bool, checkDerived bool)
| 844 | } |
| 845 | |
| 846 | func (c *Checker) getNarrowedTypeWorker(t *Type, candidate *Type, assumeTrue bool, checkDerived bool) *Type { |
| 847 | if !assumeTrue { |
| 848 | if t == candidate { |
| 849 | return c.neverType |
| 850 | } |
| 851 | if checkDerived { |
| 852 | return c.filterType(t, func(t *Type) bool { |
| 853 | return !c.isTypeDerivedFrom(t, candidate) |
| 854 | }) |
| 855 | } |
| 856 | if t.flags&TypeFlagsUnknown != 0 { |
| 857 | t = c.unknownUnionType |
| 858 | } |
| 859 | trueType := c.getNarrowedType(t, candidate, true /*assumeTrue*/, false /*checkDerived*/) |
| 860 | return c.recombineUnknownType(c.filterType(t, func(t *Type) bool { |
| 861 | return !c.isTypeSubsetOf(t, trueType) |
| 862 | })) |
| 863 | } |
| 864 | if t.flags&TypeFlagsAnyOrUnknown != 0 { |
| 865 | return candidate |
| 866 | } |
| 867 | if t == candidate { |
| 868 | return candidate |
| 869 | } |
| 870 | // We first attempt to filter the current type, narrowing constituents as appropriate and removing |
| 871 | // constituents that are unrelated to the candidate. |
| 872 | var keyPropertyName string |
| 873 | if t.flags&TypeFlagsUnion != 0 { |
| 874 | keyPropertyName = c.getKeyPropertyName(t) |
| 875 | } |
| 876 | narrowedType := c.mapType(candidate, func(n *Type) *Type { |
| 877 | // If a discriminant property is available, use that to reduce the type. |
| 878 | matching := t |
| 879 | if keyPropertyName != "" { |
| 880 | if discriminant := c.getTypeOfPropertyOfType(n, keyPropertyName); discriminant != nil { |
| 881 | if constituent := c.getConstituentTypeForKeyType(t, discriminant); constituent != nil { |
| 882 | matching = constituent |
| 883 | } |
| 884 | } |
| 885 | } |
| 886 | // For each constituent t in the current type, if t and c are directly related, pick the most |
| 887 | // specific of the two. When t and c are related in both directions, we prefer c for type predicates |
| 888 | // because that is the asserted type, but t for `instanceof` because generics aren't reflected in |
| 889 | // prototype object types. |
| 890 | var mapType func(*Type) *Type |
| 891 | if checkDerived { |
| 892 | mapType = func(t *Type) *Type { |
| 893 | switch { |
| 894 | case c.isTypeDerivedFrom(t, n): |
| 895 | return t |
| 896 | case c.isTypeDerivedFrom(n, t): |
| 897 | return n |
| 898 | } |
| 899 | return c.neverType |
| 900 | } |
| 901 | } else { |
| 902 | mapType = func(t *Type) *Type { |
| 903 | switch { |
no test coverage detected