@@ -18,7 +18,7 @@ use crate::{
1818 GLOBAL_FUNCTION_STRING_LITERAL_ID , GLOBAL_NUMBER_STRING_LITERAL_ID ,
1919 GLOBAL_OBJECT_STRING_LITERAL_ID , GLOBAL_STRING_STRING_LITERAL_ID ,
2020 GLOBAL_SYMBOL_STRING_LITERAL_ID , GLOBAL_TYPEOF_OPERATOR_RETURN_UNION_ID ,
21- GLOBAL_UNDEFINED_STRING_LITERAL_ID ,
21+ GLOBAL_UNDEFINED_ID , GLOBAL_UNDEFINED_STRING_LITERAL_ID ,
2222 } ,
2323} ;
2424
@@ -119,62 +119,6 @@ pub(super) fn flattened_expression(
119119 } )
120120 }
121121 }
122- TypeofExpression :: IterableValueOf ( expr) => {
123- let ty = resolver. resolve_and_get ( & expr. ty ) ?;
124- match ty. as_raw_data ( ) {
125- TypeData :: InstanceOf ( instance)
126- if instance. ty == GLOBAL_ARRAY_ID . into ( )
127- && instance. has_known_type_parameters ( ) =>
128- {
129- instance
130- . type_parameters
131- . first ( )
132- . map ( |param| ty. apply_module_id_to_reference ( param) )
133- . and_then ( |param| resolver. resolve_and_get ( & param) )
134- . map ( ResolvedTypeData :: to_data)
135- }
136- _ => {
137- // TODO: Handle other iterable types
138- None
139- }
140- }
141- }
142- TypeofExpression :: LogicalAnd ( expr) => {
143- let left = resolver. resolve_and_get ( & expr. left ) ?;
144- let conditional = ConditionalType :: from_resolved_data ( left, resolver) ;
145- if conditional. is_falsy ( ) {
146- Some ( left. to_data ( ) )
147- } else if conditional. is_truthy ( ) {
148- Some ( TypeData :: reference ( expr. right . clone ( ) ) )
149- } else if conditional. is_inferred ( ) {
150- let left = reference_to_falsy_subset_of ( & left. to_data ( ) , resolver)
151- . unwrap_or_else ( || expr. left . clone ( ) ) ;
152- Some ( TypeData :: union_of (
153- resolver,
154- [ left, expr. right . clone ( ) ] . into ( ) ,
155- ) )
156- } else {
157- None
158- }
159- }
160- TypeofExpression :: LogicalOr ( expr) => {
161- let left = resolver. resolve_and_get ( & expr. left ) ?;
162- let conditional = ConditionalType :: from_resolved_data ( left, resolver) ;
163- if conditional. is_truthy ( ) {
164- Some ( left. to_data ( ) )
165- } else if conditional. is_falsy ( ) {
166- Some ( TypeData :: reference ( expr. right . clone ( ) ) )
167- } else if conditional. is_inferred ( ) {
168- let left = reference_to_truthy_subset_of ( & left. to_data ( ) , resolver)
169- . unwrap_or_else ( || expr. left . clone ( ) ) ;
170- Some ( TypeData :: union_of (
171- resolver,
172- [ left, expr. right . clone ( ) ] . into ( ) ,
173- ) )
174- } else {
175- None
176- }
177- }
178122 TypeofExpression :: Destructure ( expr) => {
179123 let resolved = resolver. resolve_and_get ( & expr. ty ) ?;
180124 match ( resolved. as_raw_data ( ) , & expr. destructure_field ) {
@@ -243,6 +187,70 @@ pub(super) fn flattened_expression(
243187 }
244188 }
245189 }
190+ TypeofExpression :: Index ( expr) => {
191+ let object = resolver. resolve_and_get ( & expr. object ) ?;
192+ let element_ty = object
193+ . to_data ( )
194+ . find_element_type_at_index ( object. resolver_id ( ) , resolver, expr. index )
195+ . map_or_else ( TypeData :: unknown, ResolvedTypeData :: to_data) ;
196+ Some ( element_ty)
197+ }
198+ TypeofExpression :: IterableValueOf ( expr) => {
199+ let ty = resolver. resolve_and_get ( & expr. ty ) ?;
200+ match ty. as_raw_data ( ) {
201+ TypeData :: InstanceOf ( instance)
202+ if instance. ty == GLOBAL_ARRAY_ID . into ( )
203+ && instance. has_known_type_parameters ( ) =>
204+ {
205+ instance
206+ . type_parameters
207+ . first ( )
208+ . map ( |param| ty. apply_module_id_to_reference ( param) )
209+ . and_then ( |param| resolver. resolve_and_get ( & param) )
210+ . map ( ResolvedTypeData :: to_data)
211+ }
212+ _ => {
213+ // TODO: Handle other iterable types
214+ None
215+ }
216+ }
217+ }
218+ TypeofExpression :: LogicalAnd ( expr) => {
219+ let left = resolver. resolve_and_get ( & expr. left ) ?;
220+ let conditional = ConditionalType :: from_resolved_data ( left, resolver) ;
221+ if conditional. is_falsy ( ) {
222+ Some ( left. to_data ( ) )
223+ } else if conditional. is_truthy ( ) {
224+ Some ( TypeData :: reference ( expr. right . clone ( ) ) )
225+ } else if conditional. is_inferred ( ) {
226+ let left = reference_to_falsy_subset_of ( & left. to_data ( ) , resolver)
227+ . unwrap_or_else ( || expr. left . clone ( ) ) ;
228+ Some ( TypeData :: union_of (
229+ resolver,
230+ [ left, expr. right . clone ( ) ] . into ( ) ,
231+ ) )
232+ } else {
233+ None
234+ }
235+ }
236+ TypeofExpression :: LogicalOr ( expr) => {
237+ let left = resolver. resolve_and_get ( & expr. left ) ?;
238+ let conditional = ConditionalType :: from_resolved_data ( left, resolver) ;
239+ if conditional. is_truthy ( ) {
240+ Some ( left. to_data ( ) )
241+ } else if conditional. is_falsy ( ) {
242+ Some ( TypeData :: reference ( expr. right . clone ( ) ) )
243+ } else if conditional. is_inferred ( ) {
244+ let left = reference_to_truthy_subset_of ( & left. to_data ( ) , resolver)
245+ . unwrap_or_else ( || expr. left . clone ( ) ) ;
246+ Some ( TypeData :: union_of (
247+ resolver,
248+ [ left, expr. right . clone ( ) ] . into ( ) ,
249+ ) )
250+ } else {
251+ None
252+ }
253+ }
246254 TypeofExpression :: New ( expr) => {
247255 let resolved = resolver. resolve_and_get ( & expr. callee ) ?;
248256 if let TypeData :: Class ( class) = resolved. as_raw_data ( ) {
@@ -332,7 +340,11 @@ pub(super) fn flattened_expression(
332340 . collect ( ) ;
333341 let types = types
334342 . into_iter ( )
335- . map ( |variant| {
343+ . filter_map ( |variant| {
344+ if variant == GLOBAL_UNDEFINED_ID . into ( ) {
345+ return None ;
346+ }
347+
336348 // Resolve and flatten the type member for each variant.
337349 let variant = TypeData :: TypeofExpression ( Box :: new (
338350 TypeofExpression :: StaticMember ( TypeofStaticMemberExpression {
@@ -341,7 +353,7 @@ pub(super) fn flattened_expression(
341353 } ) ,
342354 ) ) ;
343355
344- resolver. reference_to_owned_data ( variant)
356+ Some ( resolver. reference_to_owned_data ( variant) )
345357 } )
346358 . collect ( ) ;
347359
0 commit comments