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
55fn 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 buf.push(parse_element(p)?);
70 }
71 Ok(buf)
72}
73
74pub(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
101fn 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 expect!(p, &P::Token::COMMA);
142 }
143
144 Ok(buf)
145}
146
147pub(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
163fn 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
177pub(super) fn ts_next_token_can_follow_modifier<'a>(p: &mut impl Parser<'a>) -> bool {
179 debug_assert!(p.input().syntax().typescript());
180 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
199pub 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
236fn 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
247fn 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
256fn 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
271fn 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(); 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
332pub 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 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
405pub 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
414pub 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
463pub 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 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 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 if params.is_empty() {
494 p.emit_err(span, SyntaxError::EmptyTypeArgumentList);
495 }
496
497 Ok(Box::new(TsTypeParamInstantiation { span, params }))
498}
499
500pub 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, 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
561pub 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, 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
589fn 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
607fn 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
632fn 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
651fn 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
727pub 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), false,
747 true,
749 )?;
750
751 Ok(Box::new(TsTypeParamDecl {
752 span: p.span(start),
753 params,
754 }))
755 })
756 })
757}
758
759pub 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
776pub 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 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, 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() || cur.is_greater() || cur.is_equal() || cur.is_rshift() || cur.is_greater_eq() || cur.is_plus() || cur.is_minus() || cur.is_lparen() || cur.is_no_substitution_template_literal() || cur.is_template_head() || cur.is_backquote()
886 {
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
904fn 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#[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, true, pos).map(Some);
926 }
927
928 Ok(None)
929}
930
931pub(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
950fn 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 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 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 TsEnumMemberId::Str(str_lit)
990 }
991 Expr::Tpl(mut tpl) if tpl.exprs.is_empty() => {
992 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 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
1039pub 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
1061pub 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
1078fn 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
1124fn 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
1149pub 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 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
1200fn 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
1221fn 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 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 return Ok(true);
1241 }
1242 if p.input_mut().eat(&P::Token::RPAREN) && p.input().cur().is_arrow() {
1243 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
1261fn is_ts_unambiguously_index_signature<'a, P: Parser<'a>>(p: &mut P) -> bool {
1263 debug_assert!(p.input().syntax().typescript());
1264
1265 p.assert_and_bump(&P::Token::LBRACKET); p.eat_ident_ref() && {
1270 let cur = p.input().cur();
1271 cur.is_comma() || cur.is_colon()
1272 }
1273}
1274
1275pub 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, 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
1324fn 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
1330fn 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, false).map(From::from)
1338 }
1339}
1340
1341fn 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
1363pub 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
1386fn 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
1417pub 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
1440fn 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 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 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
1519fn parse_ts_tuple_element_type<'a, P: Parser<'a>>(p: &mut P) -> PResult<TsTupleElement> {
1521 debug_assert!(p.input().syntax().typescript());
1522
1523 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 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
1561pub 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 true,
1571 false,
1572 )?;
1573
1574 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
1599pub 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(); 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
1656pub 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
1671pub 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
1691fn 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 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 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
1735fn 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
1748fn 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
1762fn 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
1794fn 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
1818fn 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
1850fn 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 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
1873fn 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
1904pub 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 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
1947fn 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 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
1982fn 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 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
2035fn 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 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
2119fn 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
2129pub 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
2141pub 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 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
2192pub 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 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
2216fn 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 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
2297fn 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, 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
2328fn 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
2348fn 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
2385fn 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
2419fn 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 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
2592pub 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 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, false),
2640 }
2641}
2642
2643pub 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, 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, true)
2749 .map(|v| v.map(make_decl_declare));
2750 }
2751
2752 Ok(None)
2753 })
2754}
2755
2756pub 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
2776fn 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, 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
2870pub 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 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}