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