swc_ecma_parser/parser/
typescript.rs

1use std::{fmt::Write, mem};
2
3use either::Either;
4use swc_atoms::{atom, Atom, Wtf8Atom};
5use swc_common::{BytePos, Span, Spanned};
6use swc_ecma_ast::*;
7
8use crate::{
9    error::SyntaxError, input::Tokens, lexer::Token, parser::util::IsSimpleParameterList, Context,
10    PResult, Parser,
11};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14enum ParsingContext {
15    EnumMembers,
16    HeritageClauseElement,
17    TupleElementTypes,
18    TypeMembers,
19    TypeParametersOrArguments,
20}
21
22#[derive(Clone, Copy, PartialEq, Eq)]
23enum UnionOrIntersection {
24    Union,
25    Intersection,
26}
27
28#[derive(Clone, Copy, PartialEq, Eq)]
29enum SignatureParsingMode {
30    TSCallSignatureDeclaration,
31    TSConstructSignatureDeclaration,
32}
33
34/// Mark as declare
35fn make_decl_declare(mut decl: Decl) -> Decl {
36    match decl {
37        Decl::Class(ref mut c) => c.declare = true,
38        Decl::Fn(ref mut f) => f.declare = true,
39        Decl::Var(ref mut v) => v.declare = true,
40        Decl::TsInterface(ref mut i) => i.declare = true,
41        Decl::TsTypeAlias(ref mut a) => a.declare = true,
42        Decl::TsEnum(ref mut e) => e.declare = true,
43        Decl::TsModule(ref mut m) => m.declare = true,
44        Decl::Using(..) => unreachable!("Using is not a valid declaration for `declare` keyword"),
45        #[cfg(swc_ast_unknown)]
46        _ => unreachable!(),
47    }
48
49    decl
50}
51
52impl<I: Tokens> Parser<I> {
53    /// `tsParseList`
54    fn parse_ts_list<T, F>(&mut self, kind: ParsingContext, mut parse_element: F) -> PResult<Vec<T>>
55    where
56        F: FnMut(&mut Self) -> PResult<T>,
57    {
58        debug_assert!(self.input().syntax().typescript());
59        let mut buf = Vec::with_capacity(8);
60        while !self.is_ts_list_terminator(kind) {
61            // Skipping "parseListElement" from the TS source since that's just for error
62            // handling.
63            buf.push(parse_element(self)?);
64        }
65        Ok(buf)
66    }
67
68    /// `tsTryParse`
69    pub(super) fn try_parse_ts_bool<F>(&mut self, op: F) -> PResult<bool>
70    where
71        F: FnOnce(&mut Self) -> PResult<Option<bool>>,
72    {
73        if !self.input().syntax().typescript() {
74            return Ok(false);
75        }
76
77        let prev_ignore_error = self.input().get_ctx().contains(Context::IgnoreError);
78        let checkpoint = self.checkpoint_save();
79        self.set_ctx(self.ctx() | Context::IgnoreError);
80        let res = op(self);
81        match res {
82            Ok(Some(res)) if res => {
83                let mut ctx = self.ctx();
84                ctx.set(Context::IgnoreError, prev_ignore_error);
85                self.input_mut().set_ctx(ctx);
86                Ok(res)
87            }
88            _ => {
89                self.checkpoint_load(checkpoint);
90                Ok(false)
91            }
92        }
93    }
94
95    /// `tsParseDelimitedList`
96    fn parse_ts_delimited_list_inner<T, F>(
97        &mut self,
98        kind: ParsingContext,
99        mut parse_element: F,
100    ) -> PResult<Vec<T>>
101    where
102        F: FnMut(&mut Self) -> PResult<(BytePos, T)>,
103    {
104        debug_assert!(self.input().syntax().typescript());
105        let mut buf = Vec::new();
106        loop {
107            trace_cur!(self, parse_ts_delimited_list_inner__element);
108
109            if self.is_ts_list_terminator(kind) {
110                break;
111            }
112
113            let (_, element) = parse_element(self)?;
114            buf.push(element);
115
116            if self.input_mut().eat(Token::Comma) {
117                continue;
118            }
119
120            if self.is_ts_list_terminator(kind) {
121                break;
122            }
123
124            if kind == ParsingContext::EnumMembers {
125                let expect = Token::Comma;
126                let cur = self.input().cur();
127                let cur = cur.to_string(self.input().get_token_value());
128                self.emit_err(
129                    self.input().cur_span(),
130                    SyntaxError::Expected(format!("{expect:?}"), cur),
131                );
132                continue;
133            }
134            // This will fail with an error about a missing comma
135            expect!(self, Token::Comma);
136        }
137
138        Ok(buf)
139    }
140
141    /// In no lexer context
142    pub(crate) fn ts_in_no_context<T, F>(&mut self, op: F) -> PResult<T>
143    where
144        F: FnOnce(&mut Self) -> PResult<T>,
145    {
146        debug_assert!(self.input().syntax().typescript());
147        trace_cur!(self, ts_in_no_context__before);
148        let res = op(self);
149        trace_cur!(self, ts_in_no_context__after);
150        res
151    }
152
153    /// `tsIsListTerminator`
154    fn is_ts_list_terminator(&mut self, kind: ParsingContext) -> bool {
155        debug_assert!(self.input().syntax().typescript());
156        let cur = self.input().cur();
157        match kind {
158            ParsingContext::EnumMembers | ParsingContext::TypeMembers => cur == Token::RBrace,
159            ParsingContext::HeritageClauseElement => {
160                matches!(cur, Token::LBrace | Token::Implements | Token::Extends)
161            }
162            ParsingContext::TupleElementTypes => cur == Token::RBracket,
163            ParsingContext::TypeParametersOrArguments => cur == Token::Gt,
164        }
165    }
166
167    /// `tsNextTokenCanFollowModifier`
168    pub(super) fn ts_next_token_can_follow_modifier(&mut self) -> bool {
169        debug_assert!(self.input().syntax().typescript());
170        // Note: TypeScript's implementation is much more complicated because
171        // more things are considered modifiers there.
172        // This implementation only handles modifiers not handled by @babel/parser
173        // itself. And "static". TODO: Would be nice to avoid lookahead. Want a
174        // hasLineBreakUpNext() method...
175        self.bump();
176
177        let cur = self.input().cur();
178        !self.input().had_line_break_before_cur()
179            && matches!(
180                cur,
181                Token::LBracket
182                    | Token::LBrace
183                    | Token::Asterisk
184                    | Token::DotDotDot
185                    | Token::Hash
186                    | Token::Str
187                    | Token::Num
188                    | Token::BigInt
189            )
190            || cur.is_word()
191    }
192
193    /// `tsTryParse`
194    pub(crate) fn try_parse_ts<T, F>(&mut self, op: F) -> Option<T>
195    where
196        F: FnOnce(&mut Self) -> PResult<Option<T>>,
197    {
198        if !self.input().syntax().typescript() {
199            return None;
200        }
201        debug_tracing!(self, "try_parse_ts");
202
203        trace_cur!(self, try_parse_ts);
204
205        let prev_ignore_error = self.input().get_ctx().contains(Context::IgnoreError);
206        let checkpoint = self.checkpoint_save();
207        self.set_ctx(self.ctx() | Context::IgnoreError);
208        let res = op(self);
209        match res {
210            Ok(Some(res)) => {
211                trace_cur!(self, try_parse_ts__success_value);
212                let mut ctx = self.ctx();
213                ctx.set(Context::IgnoreError, prev_ignore_error);
214                self.input_mut().set_ctx(ctx);
215                Some(res)
216            }
217            Ok(None) => {
218                trace_cur!(self, try_parse_ts__success_no_value);
219                self.checkpoint_load(checkpoint);
220                None
221            }
222            Err(..) => {
223                trace_cur!(self, try_parse_ts__fail);
224                self.checkpoint_load(checkpoint);
225                None
226            }
227        }
228    }
229
230    /// `tsParseTypeMemberSemicolon`
231    fn parse_ts_type_member_semicolon(&mut self) -> PResult<()> {
232        debug_assert!(self.input().syntax().typescript());
233
234        if !self.input_mut().eat(Token::Comma) {
235            self.expect_general_semi()
236        } else {
237            Ok(())
238        }
239    }
240
241    /// `tsIsStartOfConstructSignature`
242    fn is_ts_start_of_construct_signature(&mut self) -> bool {
243        debug_assert!(self.input().syntax().typescript());
244
245        self.bump();
246        let cur = self.input().cur();
247        matches!(cur, Token::LParen | Token::Lt)
248    }
249
250    /// `tsParseDelimitedList`
251    fn parse_ts_delimited_list<T, F>(
252        &mut self,
253        kind: ParsingContext,
254        mut parse_element: F,
255    ) -> PResult<Vec<T>>
256    where
257        F: FnMut(&mut Self) -> PResult<T>,
258    {
259        self.parse_ts_delimited_list_inner(kind, |p| {
260            let start = p.input().cur_pos();
261            Ok((start, parse_element(p)?))
262        })
263    }
264
265    /// `tsParseUnionOrIntersectionType`
266    fn parse_ts_union_or_intersection_type<F>(
267        &mut self,
268        kind: UnionOrIntersection,
269        mut parse_constituent_type: F,
270        operator: Token,
271    ) -> PResult<Box<TsType>>
272    where
273        F: FnMut(&mut Self) -> PResult<Box<TsType>>,
274    {
275        trace_cur!(self, parse_ts_union_or_intersection_type);
276
277        debug_assert!(self.input().syntax().typescript());
278
279        let start = self.input().cur_pos(); // include the leading operator in the start
280        self.input_mut().eat(operator);
281        trace_cur!(self, parse_ts_union_or_intersection_type__first_type);
282
283        let ty = parse_constituent_type(self)?;
284        trace_cur!(self, parse_ts_union_or_intersection_type__after_first);
285
286        if self.input().is(operator) {
287            let mut types = vec![ty];
288
289            while self.input_mut().eat(operator) {
290                trace_cur!(self, parse_ts_union_or_intersection_type__constituent);
291
292                types.push(parse_constituent_type(self)?);
293            }
294
295            return Ok(Box::new(TsType::TsUnionOrIntersectionType(match kind {
296                UnionOrIntersection::Union => TsUnionOrIntersectionType::TsUnionType(TsUnionType {
297                    span: self.span(start),
298                    types,
299                }),
300                UnionOrIntersection::Intersection => {
301                    TsUnionOrIntersectionType::TsIntersectionType(TsIntersectionType {
302                        span: self.span(start),
303                        types,
304                    })
305                }
306            })));
307        }
308        Ok(ty)
309    }
310
311    pub(crate) fn eat_any_ts_modifier(&mut self) -> PResult<bool> {
312        if self.syntax().typescript()
313            && {
314                let cur = self.input().cur();
315                matches!(
316                    cur,
317                    Token::Public | Token::Protected | Token::Private | Token::Readonly
318                )
319            }
320            && peek!(self)
321                .is_some_and(|t| t.is_word() || matches!(t, Token::LBrace | Token::LBracket))
322        {
323            let _ = self.parse_ts_modifier(&["public", "protected", "private", "readonly"], false);
324            Ok(true)
325        } else {
326            Ok(false)
327        }
328    }
329
330    /// Parses a modifier matching one the given modifier names.
331    ///
332    /// `tsParseModifier`
333    pub(crate) fn parse_ts_modifier(
334        &mut self,
335        allowed_modifiers: &[&'static str],
336        stop_on_start_of_class_static_blocks: bool,
337    ) -> PResult<Option<&'static str>> {
338        debug_assert!(self.input().syntax().typescript());
339        let pos = {
340            let cur = self.input().cur();
341            let modifier = if cur == Token::Ident {
342                cur.clone().take_unknown_ident_ref(self.input()).clone()
343            } else if cur.is_known_ident() {
344                cur.take_known_ident()
345            } else if cur == Token::In {
346                atom!("in")
347            } else if cur == Token::Const {
348                atom!("const")
349            } else if cur == Token::Error {
350                let err = self.input_mut().expect_error_token_and_bump();
351                return Err(err);
352            } else if cur == Token::Eof {
353                return Err(self.eof_error());
354            } else {
355                return Ok(None);
356            };
357            // TODO: compare atom rather than string.
358            allowed_modifiers
359                .iter()
360                .position(|s| **s == *modifier.as_str())
361        };
362        if let Some(pos) = pos {
363            if stop_on_start_of_class_static_blocks
364                && self.input().is(Token::Static)
365                && peek!(self).is_some_and(|peek| peek == Token::LBrace)
366            {
367                return Ok(None);
368            }
369            if self.try_parse_ts_bool(|p| Ok(Some(p.ts_next_token_can_follow_modifier())))? {
370                return Ok(Some(allowed_modifiers[pos]));
371            }
372        }
373        Ok(None)
374    }
375
376    fn parse_ts_bracketed_list<T, F>(
377        &mut self,
378        kind: ParsingContext,
379        parse_element: F,
380        bracket: bool,
381        skip_first_token: bool,
382    ) -> PResult<Vec<T>>
383    where
384        F: FnMut(&mut Self) -> PResult<T>,
385    {
386        debug_assert!(self.input().syntax().typescript());
387        if !skip_first_token {
388            if bracket {
389                expect!(self, Token::LBracket);
390            } else {
391                expect!(self, Token::Lt);
392            }
393        }
394        let result = self.parse_ts_delimited_list(kind, parse_element)?;
395        if bracket {
396            expect!(self, Token::RBracket);
397        } else {
398            expect!(self, Token::Gt);
399        }
400        Ok(result)
401    }
402
403    /// `tsParseThisTypeNode`
404    fn parse_ts_this_type_node(&mut self) -> PResult<TsThisType> {
405        debug_assert!(self.input().syntax().typescript());
406        expect!(self, Token::This);
407        Ok(TsThisType {
408            span: self.input().prev_span(),
409        })
410    }
411
412    /// `tsParseEntityName`
413    fn parse_ts_entity_name(&mut self, allow_reserved_words: bool) -> PResult<TsEntityName> {
414        debug_assert!(self.input().syntax().typescript());
415        trace_cur!(self, parse_ts_entity_name);
416        let start = self.input().cur_pos();
417        let init = self.parse_ident_name()?;
418        if &*init.sym == "void" {
419            let dot_start = self.input().cur_pos();
420            let dot_span = self.span(dot_start);
421            self.emit_err(dot_span, SyntaxError::TS1005)
422        }
423        let mut entity = TsEntityName::Ident(init.into());
424        while self.input_mut().eat(Token::Dot) {
425            let dot_start = self.input().cur_pos();
426            let cur = self.input().cur();
427            if cur != Token::Hash && !cur.is_word() {
428                self.emit_err(
429                    Span::new_with_checked(dot_start, dot_start),
430                    SyntaxError::TS1003,
431                );
432                return Ok(entity);
433            }
434            let left = entity;
435            let right = if allow_reserved_words {
436                self.parse_ident_name()?
437            } else {
438                self.parse_ident(false, false)?.into()
439            };
440            let span = self.span(start);
441            entity = TsEntityName::TsQualifiedName(Box::new(TsQualifiedName { span, left, right }));
442        }
443        Ok(entity)
444    }
445
446    pub(crate) fn ts_look_ahead<T, F>(&mut self, op: F) -> T
447    where
448        F: FnOnce(&mut Self) -> T,
449    {
450        debug_assert!(self.input().syntax().typescript());
451        let checkpoint = self.checkpoint_save();
452        self.set_ctx(self.ctx() | Context::IgnoreError);
453        let ret = op(self);
454        self.checkpoint_load(checkpoint);
455        ret
456    }
457
458    /// `tsParseTypeArguments`
459    pub(crate) fn parse_ts_type_args(&mut self) -> PResult<Box<TsTypeParamInstantiation>> {
460        trace_cur!(self, parse_ts_type_args);
461        debug_assert!(self.input().syntax().typescript());
462
463        let start = self.input().cur_pos();
464        let params = self.in_type(|p| {
465            // Temporarily remove a JSX parsing context, which makes us scan different
466            // tokens.
467            p.ts_in_no_context(|p| {
468                if p.input().is(Token::LShift) {
469                    p.input_mut().cut_lshift();
470                } else {
471                    expect!(p, Token::Lt);
472                }
473                p.parse_ts_delimited_list(ParsingContext::TypeParametersOrArguments, |p| {
474                    trace_cur!(p, parse_ts_type_args__arg);
475
476                    p.parse_ts_type()
477                })
478            })
479        })?;
480        // This reads the next token after the `>` too, so do this in the enclosing
481        // context. But be sure not to parse a regex in the jsx expression
482        // `<C<number> />`, so set exprAllowed = false
483        self.input_mut().set_expr_allowed(false);
484        self.expect_without_advance(Token::Gt)?;
485        let span = Span::new_with_checked(start, self.input().cur_span().hi);
486
487        // Report grammar error for empty type argument list like `I<>`.
488        if params.is_empty() {
489            self.emit_err(span, SyntaxError::EmptyTypeArgumentList);
490        }
491
492        Ok(Box::new(TsTypeParamInstantiation { span, params }))
493    }
494
495    /// `tsParseTypeReference`
496    fn parse_ts_type_ref(&mut self) -> PResult<TsTypeRef> {
497        trace_cur!(self, parse_ts_type_ref);
498        debug_assert!(self.input().syntax().typescript());
499
500        let start = self.input().cur_pos();
501
502        let has_modifier = self.eat_any_ts_modifier()?;
503
504        let type_name = self.parse_ts_entity_name(/* allow_reserved_words */ true)?;
505        trace_cur!(self, parse_ts_type_ref__type_args);
506        let type_params = if !self.input().had_line_break_before_cur()
507            && (self.input().is(Token::Lt) || self.input().is(Token::LShift))
508        {
509            let ret = self.do_outside_of_context(
510                Context::ShouldNotLexLtOrGtAsType,
511                Self::parse_ts_type_args,
512            )?;
513            self.assert_and_bump(Token::Gt);
514            Some(ret)
515        } else {
516            None
517        };
518
519        if has_modifier {
520            self.emit_err(self.span(start), SyntaxError::TS2369);
521        }
522
523        Ok(TsTypeRef {
524            span: self.span(start),
525            type_name,
526            type_params,
527        })
528    }
529
530    #[cfg_attr(
531        feature = "tracing-spans",
532        tracing::instrument(level = "debug", skip_all)
533    )]
534    pub(crate) fn parse_ts_type_ann(
535        &mut self,
536        eat_colon: bool,
537        start: BytePos,
538    ) -> PResult<Box<TsTypeAnn>> {
539        trace_cur!(self, parse_ts_type_ann);
540
541        debug_assert!(self.input().syntax().typescript());
542
543        self.in_type(|p| {
544            if eat_colon {
545                p.assert_and_bump(Token::Colon);
546            }
547
548            trace_cur!(p, parse_ts_type_ann__after_colon);
549
550            let type_ann = p.parse_ts_type()?;
551
552            Ok(Box::new(TsTypeAnn {
553                span: p.span(start),
554                type_ann,
555            }))
556        })
557    }
558
559    /// `tsParseThisTypePredicate`
560    fn parse_ts_this_type_predicate(
561        &mut self,
562        start: BytePos,
563        has_asserts_keyword: bool,
564        lhs: TsThisType,
565    ) -> PResult<TsTypePredicate> {
566        debug_assert!(self.input().syntax().typescript());
567
568        let param_name = TsThisTypeOrIdent::TsThisType(lhs);
569        let type_ann = if self.input_mut().eat(Token::Is) {
570            let cur_pos = self.input().cur_pos();
571            Some(self.parse_ts_type_ann(false, cur_pos)?)
572        } else {
573            None
574        };
575
576        Ok(TsTypePredicate {
577            span: self.span(start),
578            asserts: has_asserts_keyword,
579            param_name,
580            type_ann,
581        })
582    }
583
584    /// `tsEatThenParseType`
585    fn eat_then_parse_ts_type(&mut self, token_to_eat: Token) -> PResult<Option<Box<TsType>>> {
586        if !cfg!(feature = "typescript") {
587            return Ok(Default::default());
588        }
589
590        self.in_type(|p| {
591            if !p.input_mut().eat(token_to_eat) {
592                return Ok(None);
593            }
594
595            p.parse_ts_type().map(Some)
596        })
597    }
598
599    /// `tsExpectThenParseType`
600    fn expect_then_parse_ts_type(
601        &mut self,
602        token: Token,
603        token_str: &'static str,
604    ) -> PResult<Box<TsType>> {
605        debug_assert!(self.input().syntax().typescript());
606
607        self.in_type(|p| {
608            if !p.input_mut().eat(token) {
609                let got = format!("{:?}", p.input().cur());
610                syntax_error!(
611                    p,
612                    p.input().cur_span(),
613                    SyntaxError::Unexpected {
614                        got,
615                        expected: token_str
616                    }
617                );
618            }
619
620            p.parse_ts_type()
621        })
622    }
623
624    /// `tsParseMappedTypeParameter`
625    fn parse_ts_mapped_type_param(&mut self) -> PResult<TsTypeParam> {
626        debug_assert!(self.input().syntax().typescript());
627
628        let start = self.input().cur_pos();
629        let name = self.parse_ident_name()?;
630        let constraint = Some(self.expect_then_parse_ts_type(Token::In, "in")?);
631
632        Ok(TsTypeParam {
633            span: self.span(start),
634            name: name.into(),
635            is_in: false,
636            is_out: false,
637            is_const: false,
638            constraint,
639            default: None,
640        })
641    }
642
643    /// `tsParseTypeParameter`
644    fn parse_ts_type_param(
645        &mut self,
646        permit_in_out: bool,
647        permit_const: bool,
648    ) -> PResult<TsTypeParam> {
649        debug_assert!(self.input().syntax().typescript());
650
651        let mut is_in = false;
652        let mut is_out = false;
653        let mut is_const = false;
654
655        let start = self.input().cur_pos();
656
657        while let Some(modifer) = self.parse_ts_modifier(
658            &[
659                "public",
660                "private",
661                "protected",
662                "readonly",
663                "abstract",
664                "const",
665                "override",
666                "in",
667                "out",
668            ],
669            false,
670        )? {
671            match modifer {
672                "const" => {
673                    is_const = true;
674                    if !permit_const {
675                        self.emit_err(
676                            self.input().prev_span(),
677                            SyntaxError::TS1277(atom!("const")),
678                        );
679                    }
680                }
681                "in" => {
682                    if !permit_in_out {
683                        self.emit_err(self.input().prev_span(), SyntaxError::TS1274(atom!("in")));
684                    } else if is_in {
685                        self.emit_err(self.input().prev_span(), SyntaxError::TS1030(atom!("in")));
686                    } else if is_out {
687                        self.emit_err(
688                            self.input().prev_span(),
689                            SyntaxError::TS1029(atom!("in"), atom!("out")),
690                        );
691                    }
692                    is_in = true;
693                }
694                "out" => {
695                    if !permit_in_out {
696                        self.emit_err(self.input().prev_span(), SyntaxError::TS1274(atom!("out")));
697                    } else if is_out {
698                        self.emit_err(self.input().prev_span(), SyntaxError::TS1030(atom!("out")));
699                    }
700                    is_out = true;
701                }
702                other => self.emit_err(self.input().prev_span(), SyntaxError::TS1273(other.into())),
703            };
704        }
705
706        let name = self.in_type(Self::parse_ident_name)?.into();
707        let constraint = self.eat_then_parse_ts_type(Token::Extends)?;
708        let default = self.eat_then_parse_ts_type(Token::Eq)?;
709
710        Ok(TsTypeParam {
711            span: self.span(start),
712            name,
713            is_in,
714            is_out,
715            is_const,
716            constraint,
717            default,
718        })
719    }
720
721    /// `tsParseTypeParameter`
722    pub(crate) fn parse_ts_type_params(
723        &mut self,
724        permit_in_out: bool,
725        permit_const: bool,
726    ) -> PResult<Box<TsTypeParamDecl>> {
727        self.in_type(|p| {
728            p.ts_in_no_context(|p| {
729                let start = p.input().cur_pos();
730                let cur = p.input().cur();
731                if cur != Token::Lt && cur != Token::JSXTagStart {
732                    unexpected!(p, "< (jsx tag start)")
733                }
734                p.bump();
735
736                let params = p.parse_ts_bracketed_list(
737                    ParsingContext::TypeParametersOrArguments,
738                    |p| p.parse_ts_type_param(permit_in_out, permit_const), // bracket
739                    false,
740                    // skip_first_token
741                    true,
742                )?;
743
744                Ok(Box::new(TsTypeParamDecl {
745                    span: p.span(start),
746                    params,
747                }))
748            })
749        })
750    }
751
752    /// `tsTryParseTypeParameters`
753    pub(crate) fn try_parse_ts_type_params(
754        &mut self,
755        permit_in_out: bool,
756        permit_const: bool,
757    ) -> PResult<Option<Box<TsTypeParamDecl>>> {
758        if !cfg!(feature = "typescript") {
759            return Ok(None);
760        }
761
762        if self.input().cur() == Token::Lt {
763            return self
764                .parse_ts_type_params(permit_in_out, permit_const)
765                .map(Some);
766        }
767
768        Ok(None)
769    }
770
771    /// `tsParseTypeOrTypePredicateAnnotation`
772    pub(crate) fn parse_ts_type_or_type_predicate_ann(
773        &mut self,
774        return_token: Token,
775    ) -> PResult<Box<TsTypeAnn>> {
776        debug_assert!(self.input().syntax().typescript());
777
778        self.in_type(|p| {
779            let return_token_start = p.input().cur_pos();
780            if !p.input_mut().eat(return_token) {
781                let cur = format!("{:?}", p.input().cur());
782                let span = p.input().cur_span();
783                syntax_error!(
784                    p,
785                    span,
786                    SyntaxError::Expected(format!("{return_token:?}"), cur)
787                )
788            }
789
790            let type_pred_start = p.input().cur_pos();
791            let has_type_pred_asserts = p.input().cur() == Token::Asserts && {
792                let ctx = p.ctx();
793                peek!(p).is_some_and(|peek| {
794                    if peek.is_word() {
795                        !peek.is_reserved(ctx)
796                    } else {
797                        false
798                    }
799                })
800            };
801
802            if has_type_pred_asserts {
803                p.assert_and_bump(Token::Asserts);
804            }
805
806            let has_type_pred_is = p.is_ident_ref()
807                && peek!(p).is_some_and(|peek| peek == Token::Is)
808                && !p.input_mut().has_linebreak_between_cur_and_peeked();
809            let is_type_predicate = has_type_pred_asserts || has_type_pred_is;
810            if !is_type_predicate {
811                return p.parse_ts_type_ann(
812                    // eat_colon
813                    false,
814                    return_token_start,
815                );
816            }
817
818            let type_pred_var = p.parse_ident_name()?;
819            let type_ann = if has_type_pred_is {
820                p.assert_and_bump(Token::Is);
821                let pos = p.input().cur_pos();
822                Some(p.parse_ts_type_ann(false, pos)?)
823            } else {
824                None
825            };
826
827            let node = Box::new(TsType::TsTypePredicate(TsTypePredicate {
828                span: p.span(type_pred_start),
829                asserts: has_type_pred_asserts,
830                param_name: TsThisTypeOrIdent::Ident(type_pred_var.into()),
831                type_ann,
832            }));
833
834            Ok(Box::new(TsTypeAnn {
835                span: p.span(return_token_start),
836                type_ann: node,
837            }))
838        })
839    }
840
841    fn is_start_of_expr(&mut self) -> bool {
842        self.is_start_of_left_hand_side_expr() || {
843            let cur = self.input().cur();
844            matches!(
845                cur,
846                Token::Plus
847                    | Token::Minus
848                    | Token::Tilde
849                    | Token::Bang
850                    | Token::Delete
851                    | Token::TypeOf
852                    | Token::Void
853                    | Token::PlusPlus
854                    | Token::MinusMinus
855                    | Token::Lt
856                    | Token::Await
857                    | Token::Yield
858            ) || (cur == Token::Hash && peek!(self).is_some_and(|peek| peek.is_word()))
859        }
860    }
861
862    #[cfg_attr(
863        feature = "tracing-spans",
864        tracing::instrument(level = "debug", skip_all)
865    )]
866    pub(super) fn try_parse_ts_type_args(&mut self) -> Option<Box<TsTypeParamInstantiation>> {
867        trace_cur!(self, try_parse_ts_type_args);
868        debug_assert!(self.input().syntax().typescript());
869
870        self.try_parse_ts(|p| {
871            let type_args = p.parse_ts_type_args()?;
872            p.assert_and_bump(Token::Gt);
873            let cur = p.input().cur();
874            if matches!(
875                cur,
876                Token::Lt
877                    | Token::Gt
878                    | Token::Eq
879                    | Token::RShift
880                    | Token::GtEq
881                    | Token::Plus
882                    | Token::Minus
883                    | Token::LParen
884                    | Token::NoSubstitutionTemplateLiteral
885                    | Token::TemplateHead
886                    | Token::BackQuote
887            )
888            // these should be type
889            // arguments in function
890            // call or template, not
891            // instantiation
892            // expression
893            {
894                Ok(None)
895            } else if p.input().had_line_break_before_cur()
896                || p.input().cur().is_bin_op()
897                || !p.is_start_of_expr()
898            {
899                Ok(Some(type_args))
900            } else {
901                Ok(None)
902            }
903        })
904    }
905
906    /// `tsTryParseType`
907    fn try_parse_ts_type(&mut self) -> PResult<Option<Box<TsType>>> {
908        if !cfg!(feature = "typescript") {
909            return Ok(None);
910        }
911
912        self.eat_then_parse_ts_type(Token::Colon)
913    }
914
915    /// `tsTryParseTypeAnnotation`
916    #[cfg_attr(
917        feature = "tracing-spans",
918        tracing::instrument(level = "debug", skip_all)
919    )]
920    pub(crate) fn try_parse_ts_type_ann(&mut self) -> PResult<Option<Box<TsTypeAnn>>> {
921        if !cfg!(feature = "typescript") {
922            return Ok(None);
923        }
924
925        if self.input().is(Token::Colon) {
926            let pos = self.cur_pos();
927            return self.parse_ts_type_ann(/* eat_colon */ true, pos).map(Some);
928        }
929
930        Ok(None)
931    }
932
933    /// `tsNextThenParseType`
934    pub(super) fn next_then_parse_ts_type(&mut self) -> PResult<Box<TsType>> {
935        debug_assert!(self.input().syntax().typescript());
936
937        let result = self.in_type(|p| {
938            p.bump();
939            p.parse_ts_type()
940        });
941
942        if !self.ctx().contains(Context::InType) && {
943            let cur = self.input().cur();
944            cur == Token::Lt || cur == Token::Gt
945        } {
946            self.input_mut().merge_lt_gt();
947        }
948
949        result
950    }
951
952    /// `tsParseEnumMember`
953    fn parse_ts_enum_member(&mut self) -> PResult<TsEnumMember> {
954        debug_assert!(self.input().syntax().typescript());
955
956        let start = self.cur_pos();
957        // TypeScript allows computed property names with literal expressions in enums.
958        // Non-literal computed properties (like ["a" + "b"]) are rejected.
959        // We normalize literal computed properties (["\t"] → "\t") to keep AST simple.
960        // See https://github.com/swc-project/swc/issues/11160
961        let cur = self.input().cur();
962        let id = if cur == Token::Str {
963            TsEnumMemberId::Str(self.parse_str_lit())
964        } else if cur == Token::Num {
965            let (value, raw) = self.input_mut().expect_number_token_and_bump();
966            let mut new_raw = String::new();
967
968            new_raw.push('"');
969            new_raw.push_str(raw.as_str());
970            new_raw.push('"');
971
972            let span = self.span(start);
973
974            // Recover from error
975            self.emit_err(span, SyntaxError::TS2452);
976
977            TsEnumMemberId::Str(Str {
978                span,
979                value: value.to_string().into(),
980                raw: Some(new_raw.into()),
981            })
982        } else if cur == Token::LBracket {
983            self.assert_and_bump(Token::LBracket);
984            let expr = self.parse_expr()?;
985            self.assert_and_bump(Token::RBracket);
986            let bracket_span = self.span(start);
987
988            match *expr {
989                Expr::Lit(Lit::Str(str_lit)) => {
990                    // String literal: ["\t"] → "\t"
991                    TsEnumMemberId::Str(str_lit)
992                }
993                Expr::Tpl(mut tpl) if tpl.exprs.is_empty() => {
994                    // Template literal without substitution: [`hello`] → "hello"
995
996                    let tpl = mem::take(tpl.quasis.first_mut().unwrap());
997
998                    let span = tpl.span;
999                    let value = tpl.cooked.unwrap();
1000
1001                    TsEnumMemberId::Str(Str {
1002                        span,
1003                        value,
1004                        raw: None,
1005                    })
1006                }
1007                _ => {
1008                    // Non-literal expression: report error
1009                    self.emit_err(bracket_span, SyntaxError::TS1164);
1010                    TsEnumMemberId::Ident(Ident::new_no_ctxt(atom!(""), bracket_span))
1011                }
1012            }
1013        } else if cur == Token::Error {
1014            let err = self.input_mut().expect_error_token_and_bump();
1015            return Err(err);
1016        } else {
1017            self.parse_ident_name()
1018                .map(Ident::from)
1019                .map(TsEnumMemberId::from)?
1020        };
1021
1022        let init = if self.input_mut().eat(Token::Eq) {
1023            Some(self.parse_assignment_expr()?)
1024        } else if self.input().cur() == Token::Comma || self.input().cur() == Token::RBrace {
1025            None
1026        } else {
1027            let start = self.cur_pos();
1028            self.bump();
1029            self.input_mut().store(Token::Comma);
1030            self.emit_err(Span::new_with_checked(start, start), SyntaxError::TS1005);
1031            None
1032        };
1033
1034        Ok(TsEnumMember {
1035            span: self.span(start),
1036            id,
1037            init,
1038        })
1039    }
1040
1041    /// `tsParseEnumDeclaration`
1042    pub(crate) fn parse_ts_enum_decl(
1043        &mut self,
1044        start: BytePos,
1045        is_const: bool,
1046    ) -> PResult<Box<TsEnumDecl>> {
1047        debug_assert!(self.input().syntax().typescript());
1048
1049        let id = self.parse_ident_name()?;
1050        expect!(self, Token::LBrace);
1051        let members =
1052            self.parse_ts_delimited_list(ParsingContext::EnumMembers, Self::parse_ts_enum_member)?;
1053        expect!(self, Token::RBrace);
1054
1055        Ok(Box::new(TsEnumDecl {
1056            span: self.span(start),
1057            declare: false,
1058            is_const,
1059            id: id.into(),
1060            members,
1061        }))
1062    }
1063
1064    /// `tsTryParseTypeOrTypePredicateAnnotation`
1065    ///
1066    /// Used for parsing return types.
1067    fn try_parse_ts_type_or_type_predicate_ann(&mut self) -> PResult<Option<Box<TsTypeAnn>>> {
1068        if !cfg!(feature = "typescript") {
1069            return Ok(None);
1070        }
1071
1072        if self.input().is(Token::Colon) {
1073            self.parse_ts_type_or_type_predicate_ann(Token::Colon)
1074                .map(Some)
1075        } else {
1076            Ok(None)
1077        }
1078    }
1079
1080    /// `tsParseTemplateLiteralType`
1081    fn parse_ts_tpl_lit_type(&mut self) -> PResult<TsTplLitType> {
1082        debug_assert!(self.input().syntax().typescript());
1083
1084        let start = self.cur_pos();
1085
1086        self.assert_and_bump(Token::BackQuote);
1087
1088        let (types, quasis) = self.parse_ts_tpl_type_elements()?;
1089
1090        expect!(self, Token::BackQuote);
1091
1092        Ok(TsTplLitType {
1093            span: self.span(start),
1094            types,
1095            quasis,
1096        })
1097    }
1098
1099    fn parse_ts_tpl_type_elements(&mut self) -> PResult<(Vec<Box<TsType>>, Vec<TplElement>)> {
1100        if !cfg!(feature = "typescript") {
1101            return Ok(Default::default());
1102        }
1103
1104        trace_cur!(self, parse_tpl_elements);
1105
1106        let mut types = Vec::new();
1107
1108        let cur_elem = self.parse_tpl_element(false)?;
1109        let mut is_tail = cur_elem.tail;
1110        let mut quasis = vec![cur_elem];
1111
1112        while !is_tail {
1113            expect!(self, Token::DollarLBrace);
1114            types.push(self.parse_ts_type()?);
1115            expect!(self, Token::RBrace);
1116            let elem = self.parse_tpl_element(false)?;
1117            is_tail = elem.tail;
1118            quasis.push(elem);
1119        }
1120
1121        Ok((types, quasis))
1122    }
1123
1124    /// `tsParseLiteralTypeNode`
1125    fn parse_ts_lit_type_node(&mut self) -> PResult<TsLitType> {
1126        debug_assert!(self.input().syntax().typescript());
1127
1128        let start = self.cur_pos();
1129
1130        let lit = if self.input().is(Token::BackQuote) {
1131            let tpl = self.parse_ts_tpl_lit_type()?;
1132            TsLit::Tpl(tpl)
1133        } else {
1134            match self.parse_lit()? {
1135                Lit::BigInt(n) => TsLit::BigInt(n),
1136                Lit::Bool(n) => TsLit::Bool(n),
1137                Lit::Num(n) => TsLit::Number(n),
1138                Lit::Str(n) => TsLit::Str(n),
1139                _ => unreachable!(),
1140            }
1141        };
1142
1143        Ok(TsLitType {
1144            span: self.span(start),
1145            lit,
1146        })
1147    }
1148
1149    /// `tsParseHeritageClause`
1150    pub(crate) fn parse_ts_heritage_clause(&mut self) -> PResult<Vec<TsExprWithTypeArgs>> {
1151        debug_assert!(self.input().syntax().typescript());
1152
1153        self.parse_ts_delimited_list(
1154            ParsingContext::HeritageClauseElement,
1155            Self::parse_ts_heritage_clause_element,
1156        )
1157    }
1158
1159    fn parse_ts_heritage_clause_element(&mut self) -> PResult<TsExprWithTypeArgs> {
1160        debug_assert!(self.input().syntax().typescript());
1161
1162        let start = self.cur_pos();
1163        // Note: TS uses parseLeftHandSideExpressionOrHigher,
1164        // then has grammar errors later if it's not an EntityName.
1165
1166        let ident = self.parse_ident_name()?.into();
1167        let expr = self.parse_subscripts(Callee::Expr(ident), true, true)?;
1168        if !matches!(
1169            &*expr,
1170            Expr::Ident(..) | Expr::Member(..) | Expr::TsInstantiation(..)
1171        ) {
1172            self.emit_err(self.span(start), SyntaxError::TS2499);
1173        }
1174
1175        match *expr {
1176            Expr::TsInstantiation(v) => Ok(TsExprWithTypeArgs {
1177                span: v.span,
1178                expr: v.expr,
1179                type_args: Some(v.type_args),
1180            }),
1181            _ => {
1182                let type_args = if self.input().is(Token::Lt) {
1183                    let ret = self.parse_ts_type_args()?;
1184                    self.assert_and_bump(Token::Gt);
1185                    Some(ret)
1186                } else {
1187                    None
1188                };
1189
1190                Ok(TsExprWithTypeArgs {
1191                    span: self.span(start),
1192                    expr,
1193                    type_args,
1194                })
1195            }
1196        }
1197    }
1198
1199    /// `tsSkipParameterStart`
1200    fn skip_ts_parameter_start(&mut self) -> PResult<bool> {
1201        debug_assert!(self.input().syntax().typescript());
1202
1203        let _ = self.eat_any_ts_modifier()?;
1204
1205        let cur = self.input().cur();
1206
1207        if cur == Token::Void {
1208            Ok(false)
1209        } else if cur.is_word() || cur == Token::This {
1210            self.bump();
1211            Ok(true)
1212        } else if (cur == Token::LBrace || cur == Token::LBracket)
1213            && self.parse_binding_pat_or_ident(false).is_ok()
1214        {
1215            Ok(true)
1216        } else {
1217            Ok(false)
1218        }
1219    }
1220
1221    /// `tsIsUnambiguouslyStartOfFunctionType`
1222    fn is_ts_unambiguously_start_of_fn_type(&mut self) -> PResult<bool> {
1223        debug_assert!(self.input().syntax().typescript());
1224
1225        self.assert_and_bump(Token::LParen);
1226
1227        let cur = self.input().cur();
1228        if cur == Token::RParen || cur == Token::DotDotDot {
1229            // ( )
1230            // ( ...
1231            return Ok(true);
1232        }
1233        if self.skip_ts_parameter_start()? {
1234            let cur = self.input().cur();
1235            if matches!(
1236                cur,
1237                Token::Colon | Token::Comma | Token::Eq | Token::QuestionMark
1238            ) {
1239                // ( xxx :
1240                // ( xxx ,
1241                // ( xxx ?
1242                // ( xxx =
1243                return Ok(true);
1244            }
1245            if self.input_mut().eat(Token::RParen) && self.input().cur() == Token::Arrow {
1246                // ( xxx ) =>
1247                return Ok(true);
1248            }
1249        }
1250        Ok(false)
1251    }
1252
1253    fn is_ts_start_of_fn_type(&mut self) -> bool {
1254        debug_assert!(self.input().syntax().typescript());
1255
1256        if self.input().cur() == Token::Lt {
1257            return true;
1258        }
1259
1260        self.input().cur() == Token::LParen
1261            && self
1262                .ts_look_ahead(Self::is_ts_unambiguously_start_of_fn_type)
1263                .unwrap_or_default()
1264    }
1265
1266    /// `tsIsUnambiguouslyIndexSignature`
1267    fn is_ts_unambiguously_index_signature(&mut self) -> bool {
1268        debug_assert!(self.input().syntax().typescript());
1269
1270        // Note: babel's comment is wrong
1271        self.assert_and_bump(Token::LBracket); // Skip '['
1272
1273        // ',' is for error recovery
1274        self.eat_ident_ref() && {
1275            let cur = self.input().cur();
1276            cur == Token::Comma || cur == Token::Colon
1277        }
1278    }
1279
1280    /// `tsTryParseIndexSignature`
1281    pub(crate) fn try_parse_ts_index_signature(
1282        &mut self,
1283        index_signature_start: BytePos,
1284        readonly: bool,
1285        is_static: bool,
1286    ) -> PResult<Option<TsIndexSignature>> {
1287        if !cfg!(feature = "typescript") {
1288            return Ok(Default::default());
1289        }
1290
1291        if !(self.input().cur() == Token::LBracket
1292            && self.ts_look_ahead(Self::is_ts_unambiguously_index_signature))
1293        {
1294            return Ok(None);
1295        }
1296
1297        expect!(self, Token::LBracket);
1298
1299        let ident_start = self.cur_pos();
1300        let mut id = self.parse_ident_name().map(BindingIdent::from)?;
1301        let type_ann_start = self.cur_pos();
1302
1303        if self.input_mut().eat(Token::Comma) {
1304            self.emit_err(id.span, SyntaxError::TS1096);
1305        } else {
1306            expect!(self, Token::Colon);
1307        }
1308
1309        let type_ann = self.parse_ts_type_ann(/* eat_colon */ false, type_ann_start)?;
1310        id.span = self.span(ident_start);
1311        id.type_ann = Some(type_ann);
1312
1313        expect!(self, Token::RBracket);
1314
1315        let params = vec![TsFnParam::Ident(id)];
1316
1317        let ty = self.try_parse_ts_type_ann()?;
1318        let type_ann = ty;
1319
1320        self.parse_ts_type_member_semicolon()?;
1321
1322        Ok(Some(TsIndexSignature {
1323            span: self.span(index_signature_start),
1324            readonly,
1325            is_static,
1326            params,
1327            type_ann,
1328        }))
1329    }
1330
1331    /// `tsIsExternalModuleReference`
1332    fn is_ts_external_module_ref(&mut self) -> bool {
1333        debug_assert!(self.input().syntax().typescript());
1334        self.input().is(Token::Require) && peek!(self).is_some_and(|t| t == Token::LParen)
1335    }
1336
1337    /// `tsParseModuleReference`
1338    fn parse_ts_module_ref(&mut self) -> PResult<TsModuleRef> {
1339        debug_assert!(self.input().syntax().typescript());
1340
1341        if self.is_ts_external_module_ref() {
1342            self.parse_ts_external_module_ref().map(From::from)
1343        } else {
1344            self.parse_ts_entity_name(/* allow_reserved_words */ false)
1345                .map(From::from)
1346        }
1347    }
1348
1349    /// `tsParseExternalModuleReference`
1350    fn parse_ts_external_module_ref(&mut self) -> PResult<TsExternalModuleRef> {
1351        debug_assert!(self.input().syntax().typescript());
1352
1353        let start = self.cur_pos();
1354        expect!(self, Token::Require);
1355        expect!(self, Token::LParen);
1356        let cur = self.input().cur();
1357        if cur == Token::Error {
1358            let err = self.input_mut().expect_error_token_and_bump();
1359            return Err(err);
1360        } else if cur != Token::Str {
1361            unexpected!(self, "a string literal")
1362        }
1363        let expr = self.parse_str_lit();
1364        expect!(self, Token::RParen);
1365        Ok(TsExternalModuleRef {
1366            span: self.span(start),
1367            expr,
1368        })
1369    }
1370
1371    /// `tsParseImportEqualsDeclaration`
1372    pub(crate) fn parse_ts_import_equals_decl(
1373        &mut self,
1374        start: BytePos,
1375        id: Ident,
1376        is_export: bool,
1377        is_type_only: bool,
1378    ) -> PResult<Box<TsImportEqualsDecl>> {
1379        debug_assert!(self.input().syntax().typescript());
1380
1381        expect!(self, Token::Eq);
1382        let module_ref = self.parse_ts_module_ref()?;
1383        self.expect_general_semi()?;
1384
1385        Ok(Box::new(TsImportEqualsDecl {
1386            span: self.span(start),
1387            id,
1388            is_export,
1389            is_type_only,
1390            module_ref,
1391        }))
1392    }
1393
1394    /// `tsParseBindingListForSignature`
1395    ///
1396    /// Eats ')` at the end but does not eat `(` at start.
1397    fn parse_ts_binding_list_for_signature(&mut self) -> PResult<Vec<TsFnParam>> {
1398        if !cfg!(feature = "typescript") {
1399            return Ok(Default::default());
1400        }
1401
1402        debug_assert!(self.input().syntax().typescript());
1403
1404        let params = self.parse_formal_params()?;
1405        let mut list = Vec::with_capacity(4);
1406
1407        for param in params {
1408            let item = match param.pat {
1409                Pat::Ident(pat) => TsFnParam::Ident(pat),
1410                Pat::Array(pat) => TsFnParam::Array(pat),
1411                Pat::Object(pat) => TsFnParam::Object(pat),
1412                Pat::Rest(pat) => TsFnParam::Rest(pat),
1413                _ => unexpected!(
1414                    self,
1415                    "an identifier, [ for an array pattern, { for an object patter or ... for a \
1416                     rest pattern"
1417                ),
1418            };
1419            list.push(item);
1420        }
1421        expect!(self, Token::RParen);
1422        Ok(list)
1423    }
1424
1425    /// `tsIsStartOfMappedType`
1426    fn is_ts_start_of_mapped_type(&mut self) -> bool {
1427        debug_assert!(self.input().syntax().typescript());
1428
1429        self.bump();
1430        if self.input_mut().eat(Token::Plus) || self.input_mut().eat(Token::Minus) {
1431            return self.input().is(Token::Readonly);
1432        }
1433
1434        self.input_mut().eat(Token::Readonly);
1435
1436        if !self.input().is(Token::LBracket) {
1437            return false;
1438        }
1439        self.bump();
1440        if !self.is_ident_ref() {
1441            return false;
1442        }
1443        self.bump();
1444
1445        self.input().is(Token::In)
1446    }
1447
1448    /// `tsParseSignatureMember`
1449    fn parse_ts_signature_member(
1450        &mut self,
1451        kind: SignatureParsingMode,
1452    ) -> PResult<Either<TsCallSignatureDecl, TsConstructSignatureDecl>> {
1453        debug_assert!(self.input().syntax().typescript());
1454
1455        let start = self.cur_pos();
1456
1457        if kind == SignatureParsingMode::TSConstructSignatureDeclaration {
1458            expect!(self, Token::New);
1459        }
1460
1461        // ----- inlined self.tsFillSignature(tt.colon, node);
1462        let type_params = self.try_parse_ts_type_params(false, true)?;
1463        expect!(self, Token::LParen);
1464        let params = self.parse_ts_binding_list_for_signature()?;
1465        let type_ann = if self.input().is(Token::Colon) {
1466            Some(self.parse_ts_type_or_type_predicate_ann(Token::Colon)?)
1467        } else {
1468            None
1469        };
1470        // -----
1471
1472        self.parse_ts_type_member_semicolon()?;
1473
1474        match kind {
1475            SignatureParsingMode::TSCallSignatureDeclaration => {
1476                Ok(Either::Left(TsCallSignatureDecl {
1477                    span: self.span(start),
1478                    params,
1479                    type_ann,
1480                    type_params,
1481                }))
1482            }
1483            SignatureParsingMode::TSConstructSignatureDeclaration => {
1484                Ok(Either::Right(TsConstructSignatureDecl {
1485                    span: self.span(start),
1486                    params,
1487                    type_ann,
1488                    type_params,
1489                }))
1490            }
1491        }
1492    }
1493
1494    fn try_parse_ts_tuple_element_name(&mut self) -> Option<Pat> {
1495        if !cfg!(feature = "typescript") {
1496            return Default::default();
1497        }
1498
1499        self.try_parse_ts(|p| {
1500            let start = p.cur_pos();
1501
1502            let rest = if p.input_mut().eat(Token::DotDotDot) {
1503                Some(p.input().prev_span())
1504            } else {
1505                None
1506            };
1507
1508            let mut ident = p.parse_ident_name().map(Ident::from)?;
1509            if p.input_mut().eat(Token::QuestionMark) {
1510                ident.optional = true;
1511                ident.span = ident.span.with_hi(p.input().prev_span().hi);
1512            }
1513            expect!(p, Token::Colon);
1514
1515            Ok(Some(if let Some(dot3_token) = rest {
1516                RestPat {
1517                    span: p.span(start),
1518                    dot3_token,
1519                    arg: ident.into(),
1520                    type_ann: None,
1521                }
1522                .into()
1523            } else {
1524                ident.into()
1525            }))
1526        })
1527    }
1528
1529    /// `tsParseTupleElementType`
1530    fn parse_ts_tuple_element_type(&mut self) -> PResult<TsTupleElement> {
1531        debug_assert!(self.input().syntax().typescript());
1532
1533        // parses `...TsType[]`
1534        let start = self.cur_pos();
1535
1536        let label = self.try_parse_ts_tuple_element_name();
1537
1538        if self.input_mut().eat(Token::DotDotDot) {
1539            let type_ann = self.parse_ts_type()?;
1540            return Ok(TsTupleElement {
1541                span: self.span(start),
1542                label,
1543                ty: Box::new(TsType::TsRestType(TsRestType {
1544                    span: self.span(start),
1545                    type_ann,
1546                })),
1547            });
1548        }
1549
1550        let ty = self.parse_ts_type()?;
1551        // parses `TsType?`
1552        if self.input_mut().eat(Token::QuestionMark) {
1553            let type_ann = ty;
1554            return Ok(TsTupleElement {
1555                span: self.span(start),
1556                label,
1557                ty: Box::new(TsType::TsOptionalType(TsOptionalType {
1558                    span: self.span(start),
1559                    type_ann,
1560                })),
1561            });
1562        }
1563
1564        Ok(TsTupleElement {
1565            span: self.span(start),
1566            label,
1567            ty,
1568        })
1569    }
1570
1571    /// `tsParseTupleType`
1572    fn parse_ts_tuple_type(&mut self) -> PResult<TsTupleType> {
1573        debug_assert!(self.input().syntax().typescript());
1574
1575        let start = self.cur_pos();
1576        let elems = self.parse_ts_bracketed_list(
1577            ParsingContext::TupleElementTypes,
1578            Self::parse_ts_tuple_element_type,
1579            /* bracket */ true,
1580            /* skipFirstToken */ false,
1581        )?;
1582
1583        // Validate the elementTypes to ensure:
1584        //   No mandatory elements may follow optional elements
1585        //   If there's a rest element, it must be at the end of the tuple
1586
1587        let mut seen_optional_element = false;
1588
1589        for elem in elems.iter() {
1590            match *elem.ty {
1591                TsType::TsRestType(..) => {}
1592                TsType::TsOptionalType(..) => {
1593                    seen_optional_element = true;
1594                }
1595                _ if seen_optional_element => {
1596                    syntax_error!(self, self.span(start), SyntaxError::TsRequiredAfterOptional)
1597                }
1598                _ => {}
1599            }
1600        }
1601
1602        Ok(TsTupleType {
1603            span: self.span(start),
1604            elem_types: elems,
1605        })
1606    }
1607
1608    /// `tsParseMappedType`
1609    fn parse_ts_mapped_type(&mut self) -> PResult<TsMappedType> {
1610        debug_assert!(self.input().syntax().typescript());
1611
1612        let start = self.cur_pos();
1613        expect!(self, Token::LBrace);
1614        let mut readonly = None;
1615        let cur = self.input().cur();
1616        if cur == Token::Plus || cur == Token::Minus {
1617            readonly = Some(if cur == Token::Plus {
1618                TruePlusMinus::Plus
1619            } else {
1620                TruePlusMinus::Minus
1621            });
1622            self.bump();
1623            expect!(self, Token::Readonly)
1624        } else if self.input_mut().eat(Token::Readonly) {
1625            readonly = Some(TruePlusMinus::True);
1626        }
1627
1628        expect!(self, Token::LBracket);
1629        let type_param = self.parse_ts_mapped_type_param()?;
1630        let name_type = if self.input_mut().eat(Token::As) {
1631            Some(self.parse_ts_type()?)
1632        } else {
1633            None
1634        };
1635        expect!(self, Token::RBracket);
1636
1637        let mut optional = None;
1638        let cur = self.input().cur();
1639        if cur == Token::Plus || cur == Token::Minus {
1640            optional = Some(if cur == Token::Plus {
1641                TruePlusMinus::Plus
1642            } else {
1643                TruePlusMinus::Minus
1644            });
1645            self.bump(); // +, -
1646            expect!(self, Token::QuestionMark);
1647        } else if self.input_mut().eat(Token::QuestionMark) {
1648            optional = Some(TruePlusMinus::True);
1649        }
1650
1651        let type_ann = self.try_parse_ts_type()?;
1652        self.expect_general_semi()?;
1653        expect!(self, Token::RBrace);
1654
1655        Ok(TsMappedType {
1656            span: self.span(start),
1657            readonly,
1658            optional,
1659            type_param,
1660            name_type,
1661            type_ann,
1662        })
1663    }
1664
1665    /// `tsParseParenthesizedType`
1666    fn parse_ts_parenthesized_type(&mut self) -> PResult<TsParenthesizedType> {
1667        debug_assert!(self.input().syntax().typescript());
1668        trace_cur!(self, parse_ts_parenthesized_type);
1669
1670        let start = self.cur_pos();
1671        expect!(self, Token::LParen);
1672        let type_ann = self.parse_ts_type()?;
1673        expect!(self, Token::RParen);
1674        Ok(TsParenthesizedType {
1675            span: self.span(start),
1676            type_ann,
1677        })
1678    }
1679
1680    /// `tsParseTypeAliasDeclaration`
1681    pub(crate) fn parse_ts_type_alias_decl(
1682        &mut self,
1683        start: BytePos,
1684    ) -> PResult<Box<TsTypeAliasDecl>> {
1685        debug_assert!(self.input().syntax().typescript());
1686
1687        let id = self.parse_ident_name()?;
1688        let type_params = self.try_parse_ts_type_params(true, false)?;
1689        let type_ann = self.expect_then_parse_ts_type(Token::Eq, "=")?;
1690        self.expect_general_semi()?;
1691        Ok(Box::new(TsTypeAliasDecl {
1692            declare: false,
1693            span: self.span(start),
1694            id: id.into(),
1695            type_params,
1696            type_ann,
1697        }))
1698    }
1699
1700    /// `tsParseFunctionOrConstructorType`
1701    fn parse_ts_fn_or_constructor_type(
1702        &mut self,
1703        is_fn_type: bool,
1704    ) -> PResult<TsFnOrConstructorType> {
1705        trace_cur!(self, parse_ts_fn_or_constructor_type);
1706
1707        debug_assert!(self.input().syntax().typescript());
1708
1709        let start = self.cur_pos();
1710        let is_abstract = if !is_fn_type {
1711            self.input_mut().eat(Token::Abstract)
1712        } else {
1713            false
1714        };
1715        if !is_fn_type {
1716            expect!(self, Token::New);
1717        }
1718
1719        // ----- inlined `self.tsFillSignature(tt.arrow, node)`
1720        let type_params = self.try_parse_ts_type_params(false, true)?;
1721        expect!(self, Token::LParen);
1722        let params = self.parse_ts_binding_list_for_signature()?;
1723        let type_ann = self.parse_ts_type_or_type_predicate_ann(Token::Arrow)?;
1724        // ----- end
1725
1726        Ok(if is_fn_type {
1727            TsFnOrConstructorType::TsFnType(TsFnType {
1728                span: self.span(start),
1729                type_params,
1730                params,
1731                type_ann,
1732            })
1733        } else {
1734            TsFnOrConstructorType::TsConstructorType(TsConstructorType {
1735                span: self.span(start),
1736                type_params,
1737                params,
1738                type_ann,
1739                is_abstract,
1740            })
1741        })
1742    }
1743
1744    /// `tsParseUnionTypeOrHigher`
1745    fn parse_ts_union_type_or_higher(&mut self) -> PResult<Box<TsType>> {
1746        trace_cur!(self, parse_ts_union_type_or_higher);
1747        debug_assert!(self.input().syntax().typescript());
1748
1749        self.parse_ts_union_or_intersection_type(
1750            UnionOrIntersection::Union,
1751            Self::parse_ts_intersection_type_or_higher,
1752            Token::Pipe,
1753        )
1754    }
1755
1756    /// `tsParseIntersectionTypeOrHigher`
1757    fn parse_ts_intersection_type_or_higher(&mut self) -> PResult<Box<TsType>> {
1758        trace_cur!(self, parse_ts_intersection_type_or_higher);
1759
1760        debug_assert!(self.input().syntax().typescript());
1761
1762        self.parse_ts_union_or_intersection_type(
1763            UnionOrIntersection::Intersection,
1764            Self::parse_ts_type_operator_or_higher,
1765            Token::Ampersand,
1766        )
1767    }
1768
1769    /// `tsParseTypeOperatorOrHigher`
1770    fn parse_ts_type_operator_or_higher(&mut self) -> PResult<Box<TsType>> {
1771        trace_cur!(self, parse_ts_type_operator_or_higher);
1772        debug_assert!(self.input().syntax().typescript());
1773
1774        let operator = if self.input().is(Token::Keyof) {
1775            Some(TsTypeOperatorOp::KeyOf)
1776        } else if self.input().is(Token::Unique) {
1777            Some(TsTypeOperatorOp::Unique)
1778        } else if self.input().is(Token::Readonly) {
1779            Some(TsTypeOperatorOp::ReadOnly)
1780        } else {
1781            None
1782        };
1783
1784        match operator {
1785            Some(operator) => self
1786                .parse_ts_type_operator(operator)
1787                .map(TsType::from)
1788                .map(Box::new),
1789            None => {
1790                trace_cur!(self, parse_ts_type_operator_or_higher__not_operator);
1791
1792                if self.input().is(Token::Infer) {
1793                    self.parse_ts_infer_type().map(TsType::from).map(Box::new)
1794                } else {
1795                    let readonly = self.parse_ts_modifier(&["readonly"], false)?.is_some();
1796                    self.parse_ts_array_type_or_higher(readonly)
1797                }
1798            }
1799        }
1800    }
1801
1802    /// `tsParseTypeOperator`
1803    fn parse_ts_type_operator(&mut self, op: TsTypeOperatorOp) -> PResult<TsTypeOperator> {
1804        debug_assert!(self.input().syntax().typescript());
1805
1806        let start = self.cur_pos();
1807        match op {
1808            TsTypeOperatorOp::Unique => expect!(self, Token::Unique),
1809            TsTypeOperatorOp::KeyOf => expect!(self, Token::Keyof),
1810            TsTypeOperatorOp::ReadOnly => expect!(self, Token::Readonly),
1811            #[cfg(swc_ast_unknown)]
1812            _ => unreachable!(),
1813        }
1814
1815        let type_ann = self.parse_ts_type_operator_or_higher()?;
1816        Ok(TsTypeOperator {
1817            span: self.span(start),
1818            op,
1819            type_ann,
1820        })
1821    }
1822
1823    /// `tsParseInferType`
1824    fn parse_ts_infer_type(&mut self) -> PResult<TsInferType> {
1825        debug_assert!(self.input().syntax().typescript());
1826
1827        let start = self.cur_pos();
1828        expect!(self, Token::Infer);
1829        let type_param_name = self.parse_ident_name()?;
1830        let constraint = self.try_parse_ts(|p| {
1831            expect!(p, Token::Extends);
1832            let constraint = p.parse_ts_non_conditional_type();
1833            if p.ctx().contains(Context::DisallowConditionalTypes)
1834                || !p.input().is(Token::QuestionMark)
1835            {
1836                constraint.map(Some)
1837            } else {
1838                Ok(None)
1839            }
1840        });
1841        let type_param = TsTypeParam {
1842            span: type_param_name.span(),
1843            name: type_param_name.into(),
1844            is_in: false,
1845            is_out: false,
1846            is_const: false,
1847            constraint,
1848            default: None,
1849        };
1850        Ok(TsInferType {
1851            span: self.span(start),
1852            type_param,
1853        })
1854    }
1855
1856    /// `tsParseNonConditionalType`
1857    fn parse_ts_non_conditional_type(&mut self) -> PResult<Box<TsType>> {
1858        trace_cur!(self, parse_ts_non_conditional_type);
1859
1860        debug_assert!(self.input().syntax().typescript());
1861
1862        if self.is_ts_start_of_fn_type() {
1863            return self
1864                .parse_ts_fn_or_constructor_type(true)
1865                .map(TsType::from)
1866                .map(Box::new);
1867        }
1868        if (self.input().is(Token::Abstract) && peek!(self).is_some_and(|cur| cur == Token::New))
1869            || self.input().is(Token::New)
1870        {
1871            // As in `new () => Date`
1872            return self
1873                .parse_ts_fn_or_constructor_type(false)
1874                .map(TsType::from)
1875                .map(Box::new);
1876        }
1877
1878        self.parse_ts_union_type_or_higher()
1879    }
1880
1881    /// `tsParseArrayTypeOrHigher`
1882    fn parse_ts_array_type_or_higher(&mut self, readonly: bool) -> PResult<Box<TsType>> {
1883        trace_cur!(self, parse_ts_array_type_or_higher);
1884        debug_assert!(self.input().syntax().typescript());
1885
1886        let mut ty = self.parse_ts_non_array_type()?;
1887
1888        while !self.input().had_line_break_before_cur() && self.input_mut().eat(Token::LBracket) {
1889            if self.input_mut().eat(Token::RBracket) {
1890                ty = Box::new(TsType::TsArrayType(TsArrayType {
1891                    span: self.span(ty.span_lo()),
1892                    elem_type: ty,
1893                }));
1894            } else {
1895                let index_type = self.parse_ts_type()?;
1896                expect!(self, Token::RBracket);
1897                ty = Box::new(TsType::TsIndexedAccessType(TsIndexedAccessType {
1898                    span: self.span(ty.span_lo()),
1899                    readonly,
1900                    obj_type: ty,
1901                    index_type,
1902                }))
1903            }
1904        }
1905
1906        Ok(ty)
1907    }
1908
1909    /// Be sure to be in a type context before calling self.
1910    ///
1911    /// `tsParseType`
1912    pub(crate) fn parse_ts_type(&mut self) -> PResult<Box<TsType>> {
1913        trace_cur!(self, parse_ts_type);
1914
1915        debug_assert!(self.input().syntax().typescript());
1916
1917        // Need to set `state.inType` so that we don't parse JSX in a type context.
1918        debug_assert!(self.ctx().contains(Context::InType));
1919
1920        let start = self.cur_pos();
1921
1922        self.do_outside_of_context(Context::DisallowConditionalTypes, |p| {
1923            let ty = p.parse_ts_non_conditional_type()?;
1924            if p.input().had_line_break_before_cur() || !p.input_mut().eat(Token::Extends) {
1925                return Ok(ty);
1926            }
1927
1928            let check_type = ty;
1929            let extends_type = p.do_inside_of_context(
1930                Context::DisallowConditionalTypes,
1931                Self::parse_ts_non_conditional_type,
1932            )?;
1933
1934            expect!(p, Token::QuestionMark);
1935
1936            let true_type = p.parse_ts_type()?;
1937
1938            expect!(p, Token::Colon);
1939
1940            let false_type = p.parse_ts_type()?;
1941
1942            Ok(Box::new(TsType::TsConditionalType(TsConditionalType {
1943                span: p.span(start),
1944                check_type,
1945                extends_type,
1946                true_type,
1947                false_type,
1948            })))
1949        })
1950    }
1951
1952    /// `parsePropertyName` in babel.
1953    ///
1954    /// Returns `(computed, key)`.
1955    fn parse_ts_property_name(&mut self) -> PResult<(bool, Box<Expr>)> {
1956        let (computed, key) = if self.input_mut().eat(Token::LBracket) {
1957            let key = self.parse_assignment_expr()?;
1958            expect!(self, Token::RBracket);
1959            (true, key)
1960        } else {
1961            self.do_inside_of_context(Context::InPropertyName, |p| {
1962                // We check if it's valid for it to be a private name when we push it.
1963                let cur = p.input().cur();
1964
1965                let key = if cur == Token::Num || cur == Token::Str {
1966                    p.parse_new_expr()
1967                } else if cur == Token::Error {
1968                    let err = p.input_mut().expect_error_token_and_bump();
1969                    return Err(err);
1970                } else {
1971                    p.parse_maybe_private_name().map(|e| match e {
1972                        Either::Left(e) => {
1973                            p.emit_err(e.span(), SyntaxError::PrivateNameInInterface);
1974
1975                            e.into()
1976                        }
1977                        Either::Right(e) => e.into(),
1978                    })
1979                };
1980                key.map(|key| (false, key))
1981            })?
1982        };
1983
1984        Ok((computed, key))
1985    }
1986
1987    /// `tsParsePropertyOrMethodSignature`
1988    fn parse_ts_property_or_method_signature(
1989        &mut self,
1990        start: BytePos,
1991        readonly: bool,
1992    ) -> PResult<Either<TsPropertySignature, TsMethodSignature>> {
1993        debug_assert!(self.input().syntax().typescript());
1994
1995        let (computed, key) = self.parse_ts_property_name()?;
1996
1997        let optional = self.input_mut().eat(Token::QuestionMark);
1998
1999        let cur = self.input().cur();
2000        if matches!(cur, Token::LParen | Token::Lt) {
2001            if readonly {
2002                syntax_error!(self, SyntaxError::ReadOnlyMethod);
2003            }
2004
2005            let type_params = self.try_parse_ts_type_params(false, true)?;
2006            expect!(self, Token::LParen);
2007            let params = self.parse_ts_binding_list_for_signature()?;
2008            let type_ann = if self.input().is(Token::Colon) {
2009                self.parse_ts_type_or_type_predicate_ann(Token::Colon)
2010                    .map(Some)?
2011            } else {
2012                None
2013            };
2014            // -----
2015
2016            self.parse_ts_type_member_semicolon()?;
2017            Ok(Either::Right(TsMethodSignature {
2018                span: self.span(start),
2019                computed,
2020                key,
2021                optional,
2022                type_params,
2023                params,
2024                type_ann,
2025            }))
2026        } else {
2027            let type_ann = self.try_parse_ts_type_ann()?;
2028
2029            self.parse_ts_type_member_semicolon()?;
2030            Ok(Either::Left(TsPropertySignature {
2031                span: self.span(start),
2032                computed,
2033                readonly,
2034                key,
2035                optional,
2036                type_ann,
2037            }))
2038        }
2039    }
2040
2041    /// `tsParseTypeMember`
2042    fn parse_ts_type_member(&mut self) -> PResult<TsTypeElement> {
2043        debug_assert!(self.input().syntax().typescript());
2044
2045        fn into_type_elem(
2046            e: Either<TsCallSignatureDecl, TsConstructSignatureDecl>,
2047        ) -> TsTypeElement {
2048            match e {
2049                Either::Left(e) => e.into(),
2050                Either::Right(e) => e.into(),
2051            }
2052        }
2053        let cur = self.input().cur();
2054        if cur == Token::LParen || cur == Token::Lt {
2055            return self
2056                .parse_ts_signature_member(SignatureParsingMode::TSCallSignatureDeclaration)
2057                .map(into_type_elem);
2058        }
2059        if self.input().is(Token::New)
2060            && self.ts_look_ahead(Self::is_ts_start_of_construct_signature)
2061        {
2062            return self
2063                .parse_ts_signature_member(SignatureParsingMode::TSConstructSignatureDeclaration)
2064                .map(into_type_elem);
2065        }
2066        // Instead of fullStart, we create a node here.
2067        let start = self.cur_pos();
2068        let readonly = self.parse_ts_modifier(&["readonly"], false)?.is_some();
2069
2070        let idx = self.try_parse_ts_index_signature(start, readonly, false)?;
2071        if let Some(idx) = idx {
2072            return Ok(idx.into());
2073        }
2074
2075        if let Some(v) = self.try_parse_ts(|p| {
2076            let start = p.input().cur_pos();
2077
2078            if readonly {
2079                syntax_error!(p, SyntaxError::GetterSetterCannotBeReadonly)
2080            }
2081
2082            let is_get = if p.input_mut().eat(Token::Get) {
2083                true
2084            } else {
2085                expect!(p, Token::Set);
2086                false
2087            };
2088
2089            let (computed, key) = p.parse_ts_property_name()?;
2090
2091            if is_get {
2092                expect!(p, Token::LParen);
2093                expect!(p, Token::RParen);
2094                let type_ann = p.try_parse_ts_type_ann()?;
2095
2096                p.parse_ts_type_member_semicolon()?;
2097
2098                Ok(Some(TsTypeElement::TsGetterSignature(TsGetterSignature {
2099                    span: p.span(start),
2100                    key,
2101                    computed,
2102                    type_ann,
2103                })))
2104            } else {
2105                expect!(p, Token::LParen);
2106                let params = p.parse_ts_binding_list_for_signature()?;
2107                if params.is_empty() {
2108                    syntax_error!(p, SyntaxError::SetterParamRequired)
2109                }
2110                let param = params.into_iter().next().unwrap();
2111
2112                p.parse_ts_type_member_semicolon()?;
2113
2114                Ok(Some(TsTypeElement::TsSetterSignature(TsSetterSignature {
2115                    span: p.span(start),
2116                    key,
2117                    computed,
2118                    param,
2119                })))
2120            }
2121        }) {
2122            return Ok(v);
2123        }
2124
2125        self.parse_ts_property_or_method_signature(start, readonly)
2126            .map(|e| match e {
2127                Either::Left(e) => e.into(),
2128                Either::Right(e) => e.into(),
2129            })
2130    }
2131
2132    /// `tsParseObjectTypeMembers`
2133    fn parse_ts_object_type_members(&mut self) -> PResult<Vec<TsTypeElement>> {
2134        debug_assert!(self.input().syntax().typescript());
2135
2136        expect!(self, Token::LBrace);
2137        let members =
2138            self.parse_ts_list(ParsingContext::TypeMembers, |p| p.parse_ts_type_member())?;
2139        expect!(self, Token::RBrace);
2140        Ok(members)
2141    }
2142
2143    /// `tsParseTypeLiteral`
2144    fn parse_ts_type_lit(&mut self) -> PResult<TsTypeLit> {
2145        debug_assert!(self.input().syntax().typescript());
2146
2147        let start = self.cur_pos();
2148        let members = self.parse_ts_object_type_members()?;
2149        Ok(TsTypeLit {
2150            span: self.span(start),
2151            members,
2152        })
2153    }
2154
2155    /// `tsParseInterfaceDeclaration`
2156    pub(crate) fn parse_ts_interface_decl(
2157        &mut self,
2158        start: BytePos,
2159    ) -> PResult<Box<TsInterfaceDecl>> {
2160        debug_assert!(self.input().syntax().typescript());
2161
2162        let id = self.parse_ident_name()?;
2163        match &*id.sym {
2164            "string" | "null" | "number" | "object" | "any" | "unknown" | "boolean" | "bigint"
2165            | "symbol" | "void" | "never" | "intrinsic" => {
2166                self.emit_err(id.span, SyntaxError::TS2427);
2167            }
2168            _ => {}
2169        }
2170
2171        let type_params = self.try_parse_ts_type_params(true, false)?;
2172
2173        let extends = if self.input_mut().eat(Token::Extends) {
2174            self.parse_ts_heritage_clause()?
2175        } else {
2176            Vec::new()
2177        };
2178
2179        // Recover from
2180        //
2181        //     interface I extends A extends B {}
2182        if self.input().is(Token::Extends) {
2183            self.emit_err(self.input().cur_span(), SyntaxError::TS1172);
2184
2185            while self.input().cur() != Token::Eof && !self.input().is(Token::LBrace) {
2186                self.bump();
2187            }
2188        }
2189
2190        let body_start = self.cur_pos();
2191        let body = self.in_type(Self::parse_ts_object_type_members)?;
2192        let body = TsInterfaceBody {
2193            span: self.span(body_start),
2194            body,
2195        };
2196        Ok(Box::new(TsInterfaceDecl {
2197            span: self.span(start),
2198            declare: false,
2199            id: id.into(),
2200            type_params,
2201            extends,
2202            body,
2203        }))
2204    }
2205
2206    /// `tsParseTypeAssertion`
2207    pub(crate) fn parse_ts_type_assertion(&mut self, start: BytePos) -> PResult<TsTypeAssertion> {
2208        debug_assert!(self.input().syntax().typescript());
2209
2210        if self.input().syntax().disallow_ambiguous_jsx_like() {
2211            self.emit_err(self.span(start), SyntaxError::ReservedTypeAssertion);
2212        }
2213
2214        // Not actually necessary to set state.inType because we never reach here if JSX
2215        // plugin is enabled, but need `tsInType` to satisfy the assertion in
2216        // `tsParseType`.
2217        let type_ann = self.in_type(Self::parse_ts_type)?;
2218        expect!(self, Token::Gt);
2219        let expr = self.parse_unary_expr()?;
2220        Ok(TsTypeAssertion {
2221            span: self.span(start),
2222            type_ann,
2223            expr,
2224        })
2225    }
2226
2227    /// `tsParseImportType`
2228    fn parse_ts_import_type(&mut self) -> PResult<TsImportType> {
2229        let start = self.cur_pos();
2230        self.assert_and_bump(Token::Import);
2231
2232        expect!(self, Token::LParen);
2233
2234        let cur = self.input().cur();
2235
2236        let arg = if cur == Token::Str {
2237            self.parse_str_lit()
2238        } else if cur == Token::Error {
2239            let err = self.input_mut().expect_error_token_and_bump();
2240            return Err(err);
2241        } else {
2242            let arg_span = self.input().cur_span();
2243            self.bump();
2244            self.emit_err(arg_span, SyntaxError::TS1141);
2245            Str {
2246                span: arg_span,
2247                value: Wtf8Atom::default(),
2248                raw: Some(atom!("\"\"")),
2249            }
2250        };
2251
2252        // the "assert" keyword is deprecated and this syntax is niche, so
2253        // don't support it
2254        let attributes = if self.input_mut().eat(Token::Comma)
2255            && self.input().syntax().import_attributes()
2256            && self.input().is(Token::LBrace)
2257        {
2258            Some(self.parse_ts_call_options()?)
2259        } else {
2260            None
2261        };
2262
2263        expect!(self, Token::RParen);
2264
2265        let qualifier = if self.input_mut().eat(Token::Dot) {
2266            self.parse_ts_entity_name(false).map(Some)?
2267        } else {
2268            None
2269        };
2270
2271        let type_args = if self.input().is(Token::Lt) {
2272            let ret = self.do_outside_of_context(
2273                Context::ShouldNotLexLtOrGtAsType,
2274                Self::parse_ts_type_args,
2275            )?;
2276            self.assert_and_bump(Token::Gt);
2277            Some(ret)
2278        } else {
2279            None
2280        };
2281
2282        Ok(TsImportType {
2283            span: self.span(start),
2284            arg,
2285            qualifier,
2286            type_args,
2287            attributes,
2288        })
2289    }
2290
2291    fn parse_ts_call_options(&mut self) -> PResult<TsImportCallOptions> {
2292        debug_assert!(self.input().syntax().typescript());
2293        let start = self.cur_pos();
2294        self.assert_and_bump(Token::LBrace);
2295
2296        expect!(self, Token::With);
2297        expect!(self, Token::Colon);
2298
2299        let value = match self.parse_object_expr()? {
2300            Expr::Object(v) => v,
2301            _ => unreachable!(),
2302        };
2303        self.input_mut().eat(Token::Comma);
2304        expect!(self, Token::RBrace);
2305        Ok(TsImportCallOptions {
2306            span: self.span(start),
2307            with: Box::new(value),
2308        })
2309    }
2310
2311    /// `tsParseTypeQuery`
2312    fn parse_ts_type_query(&mut self) -> PResult<TsTypeQuery> {
2313        debug_assert!(self.input().syntax().typescript());
2314
2315        let start = self.cur_pos();
2316        expect!(self, Token::TypeOf);
2317        let expr_name = if self.input().is(Token::Import) {
2318            self.parse_ts_import_type().map(From::from)?
2319        } else {
2320            self.parse_ts_entity_name(true).map(From::from)?
2321        };
2322
2323        let type_args = if !self.input().had_line_break_before_cur() && self.input().is(Token::Lt) {
2324            let ret = self.do_outside_of_context(
2325                Context::ShouldNotLexLtOrGtAsType,
2326                Self::parse_ts_type_args,
2327            )?;
2328            self.assert_and_bump(Token::Gt);
2329            Some(ret)
2330        } else {
2331            None
2332        };
2333
2334        Ok(TsTypeQuery {
2335            span: self.span(start),
2336            expr_name,
2337            type_args,
2338        })
2339    }
2340
2341    /// `tsParseModuleBlock`
2342    fn parse_ts_module_block(&mut self) -> PResult<TsModuleBlock> {
2343        trace_cur!(self, parse_ts_module_block);
2344
2345        debug_assert!(self.input().syntax().typescript());
2346
2347        let start = self.cur_pos();
2348        expect!(self, Token::LBrace);
2349        let body = self.do_inside_of_context(Context::TsModuleBlock, |p| {
2350            p.do_outside_of_context(Context::TopLevel, |p| {
2351                p.parse_module_item_block_body(false, Some(Token::RBrace))
2352            })
2353        })?;
2354
2355        Ok(TsModuleBlock {
2356            span: self.span(start),
2357            body,
2358        })
2359    }
2360
2361    /// `tsParseModuleOrNamespaceDeclaration`
2362    fn parse_ts_module_or_ns_decl(
2363        &mut self,
2364        start: BytePos,
2365        namespace: bool,
2366    ) -> PResult<Box<TsModuleDecl>> {
2367        debug_assert!(self.input().syntax().typescript());
2368
2369        let id = self.parse_ident_name()?;
2370        let body: TsNamespaceBody = if self.input_mut().eat(Token::Dot) {
2371            let inner_start = self.cur_pos();
2372            let inner = self.parse_ts_module_or_ns_decl(inner_start, namespace)?;
2373            let inner = TsNamespaceDecl {
2374                span: inner.span,
2375                id: match inner.id {
2376                    TsModuleName::Ident(i) => i,
2377                    _ => unreachable!(),
2378                },
2379                body: Box::new(inner.body.unwrap()),
2380                declare: inner.declare,
2381                global: inner.global,
2382            };
2383            inner.into()
2384        } else {
2385            self.parse_ts_module_block().map(From::from)?
2386        };
2387
2388        Ok(Box::new(TsModuleDecl {
2389            span: self.span(start),
2390            declare: false,
2391            id: TsModuleName::Ident(id.into()),
2392            body: Some(body),
2393            global: false,
2394            namespace,
2395        }))
2396    }
2397
2398    /// `tsParseAmbientExternalModuleDeclaration`
2399    fn parse_ts_ambient_external_module_decl(
2400        &mut self,
2401        start: BytePos,
2402    ) -> PResult<Box<TsModuleDecl>> {
2403        debug_assert!(self.input().syntax().typescript());
2404
2405        let (global, id) = if self.input().is(Token::Global) {
2406            let id = self.parse_ident_name()?;
2407            (true, TsModuleName::Ident(id.into()))
2408        } else if self.input().cur() == Token::Str {
2409            let id = TsModuleName::Str(self.parse_str_lit());
2410            (false, id)
2411        } else {
2412            unexpected!(self, "global or a string literal");
2413        };
2414
2415        let body = if self.input().is(Token::LBrace) {
2416            Some(self.parse_ts_module_block().map(TsNamespaceBody::from)?)
2417        } else {
2418            self.expect_general_semi()?;
2419            None
2420        };
2421
2422        Ok(Box::new(TsModuleDecl {
2423            span: self.span(start),
2424            declare: false,
2425            id,
2426            global,
2427            body,
2428            namespace: false,
2429        }))
2430    }
2431
2432    /// `tsParseNonArrayType`
2433    fn parse_ts_non_array_type(&mut self) -> PResult<Box<TsType>> {
2434        if !cfg!(feature = "typescript") {
2435            unreachable!()
2436        }
2437        trace_cur!(self, parse_ts_non_array_type);
2438        debug_assert!(self.input().syntax().typescript());
2439
2440        let start = self.cur_pos();
2441
2442        let cur = self.input().cur();
2443        if cur.is_known_ident()
2444            || matches!(
2445                cur,
2446                Token::Ident
2447                    | Token::Void
2448                    | Token::Yield
2449                    | Token::Null
2450                    | Token::Await
2451                    | Token::Break
2452            )
2453        {
2454            if self.input().is(Token::Asserts)
2455                && peek!(self).is_some_and(|peek| peek == Token::This)
2456            {
2457                self.bump();
2458                let this_keyword = self.parse_ts_this_type_node()?;
2459                return self
2460                    .parse_ts_this_type_predicate(start, true, this_keyword)
2461                    .map(TsType::from)
2462                    .map(Box::new);
2463            }
2464            let kind = if self.input().is(Token::Void) {
2465                Some(TsKeywordTypeKind::TsVoidKeyword)
2466            } else if self.input().is(Token::Null) {
2467                Some(TsKeywordTypeKind::TsNullKeyword)
2468            } else if self.input().is(Token::Any) {
2469                Some(TsKeywordTypeKind::TsAnyKeyword)
2470            } else if self.input().is(Token::Boolean) {
2471                Some(TsKeywordTypeKind::TsBooleanKeyword)
2472            } else if self.input().is(Token::Bigint) {
2473                Some(TsKeywordTypeKind::TsBigIntKeyword)
2474            } else if self.input().is(Token::Never) {
2475                Some(TsKeywordTypeKind::TsNeverKeyword)
2476            } else if self.input().is(Token::Number) {
2477                Some(TsKeywordTypeKind::TsNumberKeyword)
2478            } else if self.input().is(Token::Object) {
2479                Some(TsKeywordTypeKind::TsObjectKeyword)
2480            } else if self.input().is(Token::String) {
2481                Some(TsKeywordTypeKind::TsStringKeyword)
2482            } else if self.input().is(Token::Symbol) {
2483                Some(TsKeywordTypeKind::TsSymbolKeyword)
2484            } else if self.input().is(Token::Unknown) {
2485                Some(TsKeywordTypeKind::TsUnknownKeyword)
2486            } else if self.input().is(Token::Undefined) {
2487                Some(TsKeywordTypeKind::TsUndefinedKeyword)
2488            } else if self.input().is(Token::Intrinsic) {
2489                Some(TsKeywordTypeKind::TsIntrinsicKeyword)
2490            } else {
2491                None
2492            };
2493
2494            let peeked_is_dot = peek!(self).is_some_and(|cur| cur == Token::Dot);
2495
2496            match kind {
2497                Some(kind) if !peeked_is_dot => {
2498                    self.bump();
2499                    return Ok(Box::new(TsType::TsKeywordType(TsKeywordType {
2500                        span: self.span(start),
2501                        kind,
2502                    })));
2503                }
2504                _ => {
2505                    return self.parse_ts_type_ref().map(TsType::from).map(Box::new);
2506                }
2507            }
2508        } else if matches!(
2509            cur,
2510            Token::BigInt | Token::Str | Token::Num | Token::True | Token::False | Token::BackQuote
2511        ) {
2512            return self
2513                .parse_ts_lit_type_node()
2514                .map(TsType::from)
2515                .map(Box::new);
2516        } else if cur == Token::NoSubstitutionTemplateLiteral || cur == Token::TemplateHead {
2517            return self.parse_tagged_tpl_ty().map(TsType::from).map(Box::new);
2518        } else if cur == Token::Minus {
2519            let start = self.cur_pos();
2520
2521            self.bump();
2522
2523            let cur = self.input().cur();
2524            if !(cur == Token::Num || cur == Token::BigInt) {
2525                unexpected!(self, "numeric literal or bigint literal")
2526            }
2527
2528            let lit = self.parse_lit()?;
2529            let lit = match lit {
2530                Lit::Num(Number { span, value, raw }) => {
2531                    let mut new_raw = String::from("-");
2532
2533                    match raw {
2534                        Some(raw) => {
2535                            new_raw.push_str(&raw);
2536                        }
2537                        _ => {
2538                            write!(new_raw, "{value}").unwrap();
2539                        }
2540                    };
2541
2542                    TsLit::Number(Number {
2543                        span,
2544                        value: -value,
2545                        raw: Some(new_raw.into()),
2546                    })
2547                }
2548                Lit::BigInt(BigInt { span, value, raw }) => {
2549                    let mut new_raw = String::from("-");
2550
2551                    match raw {
2552                        Some(raw) => {
2553                            new_raw.push_str(&raw);
2554                        }
2555                        _ => {
2556                            write!(new_raw, "{value}").unwrap();
2557                        }
2558                    };
2559
2560                    TsLit::BigInt(BigInt {
2561                        span,
2562                        value: Box::new(-*value),
2563                        raw: Some(new_raw.into()),
2564                    })
2565                }
2566                _ => unreachable!(),
2567            };
2568
2569            return Ok(Box::new(TsType::TsLitType(TsLitType {
2570                span: self.span(start),
2571                lit,
2572            })));
2573        } else if cur == Token::Import {
2574            return self.parse_ts_import_type().map(TsType::from).map(Box::new);
2575        } else if cur == Token::This {
2576            let start = self.cur_pos();
2577            let this_keyword = self.parse_ts_this_type_node()?;
2578            return if !self.input().had_line_break_before_cur() && self.input().is(Token::Is) {
2579                self.parse_ts_this_type_predicate(start, false, this_keyword)
2580                    .map(TsType::from)
2581                    .map(Box::new)
2582            } else {
2583                Ok(Box::new(TsType::TsThisType(this_keyword)))
2584            };
2585        } else if cur == Token::TypeOf {
2586            return self.parse_ts_type_query().map(TsType::from).map(Box::new);
2587        } else if cur == Token::LBrace {
2588            return if self.ts_look_ahead(Self::is_ts_start_of_mapped_type) {
2589                self.parse_ts_mapped_type().map(TsType::from).map(Box::new)
2590            } else {
2591                self.parse_ts_type_lit().map(TsType::from).map(Box::new)
2592            };
2593        } else if cur == Token::LBracket {
2594            return self.parse_ts_tuple_type().map(TsType::from).map(Box::new);
2595        } else if cur == Token::LParen {
2596            return self
2597                .parse_ts_parenthesized_type()
2598                .map(TsType::from)
2599                .map(Box::new);
2600        }
2601
2602        //   switch (self.state.type) {
2603        //   }
2604
2605        unexpected!(
2606            self,
2607            "an identifier, void, yield, null, await, break, a string literal, a numeric literal, \
2608             true, false, `, -, import, this, typeof, {, [, ("
2609        )
2610    }
2611
2612    /// `tsParseExpressionStatement`
2613    pub(crate) fn parse_ts_expr_stmt(
2614        &mut self,
2615        decorators: Vec<Decorator>,
2616        expr: Ident,
2617    ) -> PResult<Option<Decl>> {
2618        if !cfg!(feature = "typescript") {
2619            return Ok(Default::default());
2620        }
2621
2622        let start = expr.span_lo();
2623
2624        match &*expr.sym {
2625            "declare" => {
2626                let decl = self.try_parse_ts_declare(start, decorators)?;
2627                if let Some(decl) = decl {
2628                    Ok(Some(make_decl_declare(decl)))
2629                } else {
2630                    Ok(None)
2631                }
2632            }
2633            "global" => {
2634                // `global { }` (with no `declare`) may appear inside an ambient module
2635                // declaration.
2636                // Would like to use tsParseAmbientExternalModuleDeclaration here, but already
2637                // ran past "global".
2638                if self.input().is(Token::LBrace) {
2639                    let global = true;
2640                    let id = TsModuleName::Ident(expr);
2641                    let body = self
2642                        .parse_ts_module_block()
2643                        .map(TsNamespaceBody::from)
2644                        .map(Some)?;
2645                    Ok(Some(
2646                        TsModuleDecl {
2647                            span: self.span(start),
2648                            global,
2649                            declare: false,
2650                            namespace: false,
2651                            id,
2652                            body,
2653                        }
2654                        .into(),
2655                    ))
2656                } else {
2657                    Ok(None)
2658                }
2659            }
2660            _ => self.parse_ts_decl(start, decorators, expr.sym, /* next */ false),
2661        }
2662    }
2663
2664    /// `tsTryParseDeclare`
2665    pub(crate) fn try_parse_ts_declare(
2666        &mut self,
2667        start: BytePos,
2668        decorators: Vec<Decorator>,
2669    ) -> PResult<Option<Decl>> {
2670        if !self.syntax().typescript() {
2671            return Ok(None);
2672        }
2673
2674        if self
2675            .ctx()
2676            .contains(Context::InDeclare | Context::TsModuleBlock)
2677        {
2678            let span_of_declare = self.span(start);
2679            self.emit_err(span_of_declare, SyntaxError::TS1038);
2680        }
2681
2682        let declare_start = start;
2683        self.do_inside_of_context(Context::InDeclare, |p| {
2684            if p.input().is(Token::Function) {
2685                return p
2686                    .parse_fn_decl(decorators)
2687                    .map(|decl| match decl {
2688                        Decl::Fn(f) => FnDecl {
2689                            declare: true,
2690                            function: Box::new(Function {
2691                                span: Span {
2692                                    lo: declare_start,
2693                                    ..f.function.span
2694                                },
2695                                ..*f.function
2696                            }),
2697                            ..f
2698                        }
2699                        .into(),
2700                        _ => decl,
2701                    })
2702                    .map(Some);
2703            }
2704
2705            if p.input().is(Token::Class) {
2706                return p
2707                    .parse_class_decl(start, start, decorators, false)
2708                    .map(|decl| match decl {
2709                        Decl::Class(c) => ClassDecl {
2710                            declare: true,
2711                            class: Box::new(Class {
2712                                span: Span {
2713                                    lo: declare_start,
2714                                    ..c.class.span
2715                                },
2716                                ..*c.class
2717                            }),
2718                            ..c
2719                        }
2720                        .into(),
2721                        _ => decl,
2722                    })
2723                    .map(Some);
2724            }
2725
2726            if p.input().is(Token::Const) && peek!(p).is_some_and(|peek| peek == Token::Enum) {
2727                p.assert_and_bump(Token::Const);
2728                p.assert_and_bump(Token::Enum);
2729
2730                return p
2731                    .parse_ts_enum_decl(start, /* is_const */ true)
2732                    .map(|decl| TsEnumDecl {
2733                        declare: true,
2734                        span: Span {
2735                            lo: declare_start,
2736                            ..decl.span
2737                        },
2738                        ..*decl
2739                    })
2740                    .map(Box::new)
2741                    .map(From::from)
2742                    .map(Some);
2743            }
2744
2745            let cur = p.input().cur();
2746            if matches!(cur, Token::Const | Token::Var | Token::Let) {
2747                return p
2748                    .parse_var_stmt(false)
2749                    .map(|decl| VarDecl {
2750                        declare: true,
2751                        span: Span {
2752                            lo: declare_start,
2753                            ..decl.span
2754                        },
2755                        ..*decl
2756                    })
2757                    .map(Box::new)
2758                    .map(From::from)
2759                    .map(Some);
2760            }
2761
2762            if p.input().is(Token::Global) {
2763                return p
2764                    .parse_ts_ambient_external_module_decl(start)
2765                    .map(Decl::from)
2766                    .map(make_decl_declare)
2767                    .map(Some);
2768            } else if p.input().cur().is_word() {
2769                let value = p.input_mut().cur().take_word(p.input_mut()).unwrap();
2770                return p
2771                    .parse_ts_decl(start, decorators, value, /* next */ true)
2772                    .map(|v| v.map(make_decl_declare));
2773            }
2774
2775            Ok(None)
2776        })
2777    }
2778
2779    /// `tsTryParseExportDeclaration`
2780    ///
2781    /// Note: this won't be called unless the keyword is allowed in
2782    /// `shouldParseExportDeclaration`.
2783    pub(crate) fn try_parse_ts_export_decl(
2784        &mut self,
2785        decorators: Vec<Decorator>,
2786        value: Atom,
2787    ) -> Option<Decl> {
2788        if !cfg!(feature = "typescript") {
2789            return None;
2790        }
2791
2792        self.try_parse_ts(|p| {
2793            let start = p.cur_pos();
2794            let opt = p.parse_ts_decl(start, decorators, value, true)?;
2795            Ok(opt)
2796        })
2797    }
2798
2799    /// Common to tsTryParseDeclare, tsTryParseExportDeclaration, and
2800    /// tsParseExpressionStatement.
2801    ///
2802    /// `tsParseDeclaration`
2803    fn parse_ts_decl(
2804        &mut self,
2805        start: BytePos,
2806        decorators: Vec<Decorator>,
2807        value: Atom,
2808        next: bool,
2809    ) -> PResult<Option<Decl>> {
2810        if !cfg!(feature = "typescript") {
2811            return Ok(Default::default());
2812        }
2813
2814        match &*value {
2815            "abstract" => {
2816                if next
2817                    || (self.input().is(Token::Class) && !self.input().had_line_break_before_cur())
2818                {
2819                    if next {
2820                        self.bump();
2821                    }
2822                    return Ok(Some(self.parse_class_decl(start, start, decorators, true)?));
2823                }
2824            }
2825
2826            "enum" => {
2827                if next || self.is_ident_ref() {
2828                    if next {
2829                        self.bump();
2830                    }
2831                    return self
2832                        .parse_ts_enum_decl(start, /* is_const */ false)
2833                        .map(From::from)
2834                        .map(Some);
2835                }
2836            }
2837
2838            "interface" => {
2839                if next || (self.is_ident_ref()) {
2840                    if next {
2841                        self.bump();
2842                    }
2843
2844                    return self
2845                        .parse_ts_interface_decl(start)
2846                        .map(From::from)
2847                        .map(Some);
2848                }
2849            }
2850
2851            "module" if !self.input().had_line_break_before_cur() => {
2852                if next {
2853                    self.bump();
2854                }
2855
2856                let cur = self.input().cur();
2857                if cur == Token::Str {
2858                    return self
2859                        .parse_ts_ambient_external_module_decl(start)
2860                        .map(From::from)
2861                        .map(Some);
2862                } else if cur == Token::Error {
2863                    let err = self.input_mut().expect_error_token_and_bump();
2864                    return Err(err);
2865                } else if cur == Token::Eof {
2866                    return Err(self.eof_error());
2867                } else if next || self.is_ident_ref() {
2868                    return self
2869                        .parse_ts_module_or_ns_decl(start, false)
2870                        .map(From::from)
2871                        .map(Some);
2872                }
2873            }
2874
2875            "namespace" => {
2876                if next || self.is_ident_ref() {
2877                    if next {
2878                        self.bump();
2879                    }
2880                    return self
2881                        .parse_ts_module_or_ns_decl(start, true)
2882                        .map(From::from)
2883                        .map(Some);
2884                }
2885            }
2886
2887            "type" => {
2888                if next || (!self.input().had_line_break_before_cur() && self.is_ident_ref()) {
2889                    if next {
2890                        self.bump();
2891                    }
2892                    return self
2893                        .parse_ts_type_alias_decl(start)
2894                        .map(From::from)
2895                        .map(Some);
2896                }
2897            }
2898
2899            _ => {}
2900        }
2901
2902        Ok(None)
2903    }
2904
2905    /// `tsTryParseGenericAsyncArrowFunction`
2906    pub(crate) fn try_parse_ts_generic_async_arrow_fn(
2907        &mut self,
2908        start: BytePos,
2909    ) -> PResult<Option<ArrowExpr>> {
2910        if !cfg!(feature = "typescript") {
2911            return Ok(Default::default());
2912        }
2913
2914        let cur = self.input().cur();
2915        let res = if cur == Token::Lt || cur == Token::JSXTagStart {
2916            self.try_parse_ts(|p| {
2917                let type_params = p.parse_ts_type_params(false, false)?;
2918                // Don't use overloaded parseFunctionParams which would look for "<" again.
2919                expect!(p, Token::LParen);
2920                let params: Vec<Pat> = p
2921                    .parse_formal_params()?
2922                    .into_iter()
2923                    .map(|p| p.pat)
2924                    .collect();
2925                expect!(p, Token::RParen);
2926                let return_type = p.try_parse_ts_type_or_type_predicate_ann()?;
2927                expect!(p, Token::Arrow);
2928
2929                Ok(Some((type_params, params, return_type)))
2930            })
2931        } else {
2932            None
2933        };
2934
2935        let (type_params, params, return_type) = match res {
2936            Some(v) => v,
2937            None => return Ok(None),
2938        };
2939
2940        self.do_inside_of_context(Context::InAsync, |p| {
2941            p.do_outside_of_context(Context::InGenerator, |p| {
2942                let is_generator = false;
2943                let is_async = true;
2944                let body = p.parse_fn_block_or_expr_body(
2945                    true,
2946                    false,
2947                    true,
2948                    params.is_simple_parameter_list(),
2949                )?;
2950                Ok(Some(ArrowExpr {
2951                    span: p.span(start),
2952                    body,
2953                    is_async,
2954                    is_generator,
2955                    type_params: Some(type_params),
2956                    params,
2957                    return_type,
2958                    ..Default::default()
2959                }))
2960            })
2961        })
2962    }
2963}
2964
2965#[cfg(test)]
2966mod tests {
2967    use swc_atoms::atom;
2968    use swc_common::DUMMY_SP;
2969    use swc_ecma_ast::*;
2970    use swc_ecma_visit::assert_eq_ignore_span;
2971
2972    use crate::{test_parser, Syntax};
2973
2974    #[test]
2975    fn issue_708_1() {
2976        let actual = test_parser(
2977            "type test = -1;",
2978            Syntax::Typescript(Default::default()),
2979            |p| p.parse_module(),
2980        );
2981
2982        let expected = Module {
2983            span: DUMMY_SP,
2984            shebang: None,
2985            body: {
2986                let first = TsTypeAliasDecl {
2987                    span: DUMMY_SP,
2988                    declare: false,
2989                    id: Ident::new_no_ctxt(atom!("test"), DUMMY_SP),
2990                    type_params: None,
2991                    type_ann: Box::new(TsType::TsLitType(TsLitType {
2992                        span: DUMMY_SP,
2993                        lit: TsLit::Number(Number {
2994                            span: DUMMY_SP,
2995                            value: -1.0,
2996                            raw: Some(atom!("-1")),
2997                        }),
2998                    })),
2999                }
3000                .into();
3001                vec![first]
3002            },
3003        };
3004
3005        assert_eq_ignore_span!(actual, expected);
3006    }
3007
3008    #[test]
3009    fn issue_708_2() {
3010        let actual = test_parser(
3011            "const t = -1;",
3012            Syntax::Typescript(Default::default()),
3013            |p| p.parse_module(),
3014        );
3015
3016        let expected = Module {
3017            span: DUMMY_SP,
3018            shebang: None,
3019            body: {
3020                let second = VarDecl {
3021                    span: DUMMY_SP,
3022                    kind: VarDeclKind::Const,
3023                    declare: false,
3024                    decls: vec![VarDeclarator {
3025                        span: DUMMY_SP,
3026                        name: Pat::Ident(Ident::new_no_ctxt(atom!("t"), DUMMY_SP).into()),
3027                        init: Some(Box::new(Expr::Unary(UnaryExpr {
3028                            span: DUMMY_SP,
3029                            op: op!(unary, "-"),
3030                            arg: Box::new(Expr::Lit(Lit::Num(Number {
3031                                span: DUMMY_SP,
3032                                value: 1.0,
3033                                raw: Some(atom!("1")),
3034                            }))),
3035                        }))),
3036                        definite: false,
3037                    }],
3038                    ..Default::default()
3039                }
3040                .into();
3041                vec![second]
3042            },
3043        };
3044
3045        assert_eq_ignore_span!(actual, expected);
3046    }
3047}