oxc_ast/ast/
ts.rs

1//! TypeScript Definitions
2//!
3//! This module contains AST node definitions for TypeScript syntax including:
4//! - Type annotations and declarations
5//! - Interfaces and type aliases
6//! - Enums and namespaces
7//! - TypeScript-specific expressions
8//! - Import/export extensions
9//!
10//! ## References
11//! - [AST Spec](https://github.com/typescript-eslint/typescript-eslint/tree/v8.9.0/packages/ast-spec)
12//! - [Archived TypeScript spec](https://github.com/microsoft/TypeScript/blob/3c99d50da5a579d9fa92d02664b1b66d4ff55944/doc/spec-ARCHIVED.md)
13#![expect(
14    missing_docs, // TODO: document individual struct fields
15    clippy::enum_variant_names,
16)]
17
18// NB: `#[span]`, `#[scope(...)]`,`#[visit(...)]` and `#[generate_derive(...)]` do NOT do anything to the code.
19// They are purely markers for codegen used in `tasks/ast_tools` and `crates/oxc_traverse/scripts`. See docs in those crates.
20// Read [`macro@oxc_ast_macros::ast`] for more information.
21
22use std::cell::Cell;
23
24use oxc_allocator::{Box, CloneIn, Dummy, GetAddress, TakeIn, Vec};
25use oxc_ast_macros::ast;
26use oxc_estree::ESTree;
27use oxc_span::{Atom, ContentEq, GetSpan, GetSpanMut, Span};
28use oxc_syntax::scope::ScopeId;
29
30use super::{inherit_variants, js::*, literal::*};
31
32/// TypeScript `this` parameter
33///
34/// ## Example
35/// ```ts
36/// type T = (this: string, a: number) => void
37/// //        ^^^^^^^^^^^^
38/// ```
39///
40/// ## Reference
41/// * [TypeScript Handbook - `this` parameters](https://www.typescriptlang.org/docs/handbook/2/functions.html#this-parameters)
42#[ast(visit)]
43#[derive(Debug)]
44#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
45#[estree(
46    rename = "Identifier",
47    add_fields(decorators = EmptyArray, name = This, optional = False),
48    field_order(decorators, name, optional, type_annotation, span),
49)]
50pub struct TSThisParameter<'a> {
51    pub span: Span,
52    #[estree(skip)]
53    pub this_span: Span,
54    /// Type type the `this` keyword will have in the function
55    pub type_annotation: Option<Box<'a, TSTypeAnnotation<'a>>>,
56}
57
58/// Enum Declaration
59///
60/// `const_opt` enum `BindingIdentifier` { `EnumBody_opt` }
61///
62/// ## Examples
63///
64/// ```ts
65/// enum Foo {
66///     A,
67///     B
68/// }
69/// // `Bar` has `r#const` set to `true`
70/// const enum Bar {
71///     A,
72///     B
73/// }
74/// ```
75///
76/// ## Reference
77/// * [TypeScript Handbook - Enums](https://www.typescriptlang.org/docs/handbook/enums.html)
78#[ast(visit)]
79#[scope]
80#[derive(Debug)]
81#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
82pub struct TSEnumDeclaration<'a> {
83    pub span: Span,
84    pub id: BindingIdentifier<'a>,
85    #[scope(enter_before)]
86    pub body: TSEnumBody<'a>,
87    /// `true` for const enums
88    pub r#const: bool,
89    pub declare: bool,
90    pub scope_id: Cell<Option<ScopeId>>,
91}
92
93/// Enum Body
94///
95/// The body of a [`TSEnumDeclaration`].
96///
97/// ## Example
98/// ```ts
99/// enum Foo { A }
100///          ^^^^^
101/// enum Bar
102///   { B }
103///   ^^^^^
104/// ```
105#[ast(visit)]
106#[derive(Debug)]
107#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
108pub struct TSEnumBody<'a> {
109    pub span: Span,
110    pub members: Vec<'a, TSEnumMember<'a>>,
111}
112
113/// Enum Member
114///
115/// A member property in a [`TSEnumBody`].
116///
117/// ## Example
118/// ```ts
119/// enum Foo {
120/// //  _ id
121///     A = 1,
122/// //      ^ initializer
123///     B // initializer will be `None`
124///
125/// }
126/// ```
127///
128/// ## Reference
129/// * [TypeScript Handbook - Enums](https://www.typescriptlang.org/docs/handbook/enums.html)
130#[ast(visit)]
131#[derive(Debug)]
132#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
133#[estree(add_fields(computed = TSEnumMemberComputed))]
134pub struct TSEnumMember<'a> {
135    pub span: Span,
136    pub id: TSEnumMemberName<'a>,
137    pub initializer: Option<Expression<'a>>,
138}
139
140/// TS Enum Member Name
141///
142/// ## Example
143/// ```ts
144/// enum ValidEnum {
145///   identifier,
146///   'string',
147///   ['computed-string'],
148///   [`computed-template`],
149///   // These are invalid syntax
150///   // `template`,
151///   // [computedIdentifier],
152/// }
153/// ```
154#[ast(visit)]
155#[derive(Debug)]
156#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ESTree)]
157pub enum TSEnumMemberName<'a> {
158    Identifier(Box<'a, IdentifierName<'a>>) = 0,
159    String(Box<'a, StringLiteral<'a>>) = 1,
160    ComputedString(Box<'a, StringLiteral<'a>>) = 2,
161    ComputedTemplateString(Box<'a, TemplateLiteral<'a>>) = 3,
162}
163
164/// TypeScript Type Annotation
165///
166/// An annotation on a variable declaration, parameter, etc.
167///
168/// ## Example
169/// ```ts
170/// const x: number = 1;
171/// //     ^^^^^^^^
172///
173/// function foo(x: number): number { return x; }
174/// //            ^^^^^^^^ ^^^^^^^^
175/// ```
176#[ast(visit)]
177#[derive(Debug)]
178#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
179pub struct TSTypeAnnotation<'a> {
180    /// starts at the `:` token and ends at the end of the type annotation
181    pub span: Span,
182    /// The actual type in the annotation
183    pub type_annotation: TSType<'a>,
184}
185
186/// TypeScript Literal Type
187///
188/// A type that is a literal value. Wraps a [`TSLiteral`].
189///
190/// ## Example
191/// ```ts
192/// const x: 'foo' = 'foo';
193/// //       ^^^^^
194///
195/// type NonZero<N> = N extends 0 ? never : N;
196/// //                          ^
197/// type Three = NonZero<3>;
198/// //                   ^
199/// ```
200#[ast(visit)]
201#[derive(Debug)]
202#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
203pub struct TSLiteralType<'a> {
204    pub span: Span,
205    pub literal: TSLiteral<'a>,
206}
207
208/// A literal in a [`TSLiteralType`].
209#[ast(visit)]
210#[derive(Debug)]
211#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ESTree)]
212pub enum TSLiteral<'a> {
213    BooleanLiteral(Box<'a, BooleanLiteral>) = 0,
214    NumericLiteral(Box<'a, NumericLiteral<'a>>) = 1,
215    BigIntLiteral(Box<'a, BigIntLiteral<'a>>) = 2,
216    StringLiteral(Box<'a, StringLiteral<'a>>) = 3,
217    TemplateLiteral(Box<'a, TemplateLiteral<'a>>) = 4,
218    UnaryExpression(Box<'a, UnaryExpression<'a>>) = 5,
219}
220
221/// TypeScript Type
222///
223/// This is the root-level type for TypeScript types, similar to how [`Expression`] is for
224/// expressions.
225///
226/// ## Examples
227/// ```ts
228/// // Foo is a TSTypeAlias
229/// type Foo = number | string
230/// //         ^^^^^^^^^^^^^^^ TSType::TSUnionType
231/// ```
232#[ast(visit)]
233#[derive(Debug)]
234#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ESTree)]
235pub enum TSType<'a> {
236    // Keyword
237    TSAnyKeyword(Box<'a, TSAnyKeyword>) = 0,
238    TSBigIntKeyword(Box<'a, TSBigIntKeyword>) = 1,
239    TSBooleanKeyword(Box<'a, TSBooleanKeyword>) = 2,
240    TSIntrinsicKeyword(Box<'a, TSIntrinsicKeyword>) = 3,
241    TSNeverKeyword(Box<'a, TSNeverKeyword>) = 4,
242    TSNullKeyword(Box<'a, TSNullKeyword>) = 5,
243    TSNumberKeyword(Box<'a, TSNumberKeyword>) = 6,
244    TSObjectKeyword(Box<'a, TSObjectKeyword>) = 7,
245    TSStringKeyword(Box<'a, TSStringKeyword>) = 8,
246    TSSymbolKeyword(Box<'a, TSSymbolKeyword>) = 9,
247    TSUndefinedKeyword(Box<'a, TSUndefinedKeyword>) = 11,
248    TSUnknownKeyword(Box<'a, TSUnknownKeyword>) = 12,
249    TSVoidKeyword(Box<'a, TSVoidKeyword>) = 13,
250    // Compound
251    TSArrayType(Box<'a, TSArrayType<'a>>) = 14,
252    TSConditionalType(Box<'a, TSConditionalType<'a>>) = 15,
253    TSConstructorType(Box<'a, TSConstructorType<'a>>) = 16,
254    TSFunctionType(Box<'a, TSFunctionType<'a>>) = 17,
255    TSImportType(Box<'a, TSImportType<'a>>) = 18,
256    TSIndexedAccessType(Box<'a, TSIndexedAccessType<'a>>) = 19,
257    TSInferType(Box<'a, TSInferType<'a>>) = 20,
258    TSIntersectionType(Box<'a, TSIntersectionType<'a>>) = 21,
259    TSLiteralType(Box<'a, TSLiteralType<'a>>) = 22,
260    TSMappedType(Box<'a, TSMappedType<'a>>) = 23,
261    TSNamedTupleMember(Box<'a, TSNamedTupleMember<'a>>) = 24,
262    TSTemplateLiteralType(Box<'a, TSTemplateLiteralType<'a>>) = 26,
263    TSThisType(Box<'a, TSThisType>) = 10,
264    TSTupleType(Box<'a, TSTupleType<'a>>) = 27,
265    TSTypeLiteral(Box<'a, TSTypeLiteral<'a>>) = 28,
266    TSTypeOperatorType(Box<'a, TSTypeOperator<'a>>) = 29,
267    TSTypePredicate(Box<'a, TSTypePredicate<'a>>) = 30,
268    TSTypeQuery(Box<'a, TSTypeQuery<'a>>) = 31,
269    TSTypeReference(Box<'a, TSTypeReference<'a>>) = 32,
270    TSUnionType(Box<'a, TSUnionType<'a>>) = 33,
271    TSParenthesizedType(Box<'a, TSParenthesizedType<'a>>) = 34,
272    // JSDoc
273    JSDocNullableType(Box<'a, JSDocNullableType<'a>>) = 35,
274    JSDocNonNullableType(Box<'a, JSDocNonNullableType<'a>>) = 36,
275    JSDocUnknownType(Box<'a, JSDocUnknownType>) = 37,
276}
277
278/// Macro for matching `TSType`'s variants.
279#[macro_export]
280macro_rules! match_ts_type {
281    ($ty:ident) => {
282        $ty::TSAnyKeyword(_)
283            | $ty::TSBigIntKeyword(_)
284            | $ty::TSBooleanKeyword(_)
285            | $ty::TSIntrinsicKeyword(_)
286            | $ty::TSNeverKeyword(_)
287            | $ty::TSNullKeyword(_)
288            | $ty::TSNumberKeyword(_)
289            | $ty::TSObjectKeyword(_)
290            | $ty::TSStringKeyword(_)
291            | $ty::TSSymbolKeyword(_)
292            | $ty::TSThisType(_)
293            | $ty::TSUndefinedKeyword(_)
294            | $ty::TSUnknownKeyword(_)
295            | $ty::TSVoidKeyword(_)
296            | $ty::TSArrayType(_)
297            | $ty::TSConditionalType(_)
298            | $ty::TSConstructorType(_)
299            | $ty::TSFunctionType(_)
300            | $ty::TSImportType(_)
301            | $ty::TSIndexedAccessType(_)
302            | $ty::TSInferType(_)
303            | $ty::TSIntersectionType(_)
304            | $ty::TSLiteralType(_)
305            | $ty::TSMappedType(_)
306            | $ty::TSNamedTupleMember(_)
307            | $ty::TSTemplateLiteralType(_)
308            | $ty::TSTupleType(_)
309            | $ty::TSTypeLiteral(_)
310            | $ty::TSTypeOperatorType(_)
311            | $ty::TSTypePredicate(_)
312            | $ty::TSTypeQuery(_)
313            | $ty::TSTypeReference(_)
314            | $ty::TSUnionType(_)
315            | $ty::TSParenthesizedType(_)
316            | $ty::JSDocNullableType(_)
317            | $ty::JSDocNonNullableType(_)
318            | $ty::JSDocUnknownType(_)
319    };
320}
321pub use match_ts_type;
322
323/// TypeScript Conditional Type
324///
325/// ## Example
326/// ```ts
327/// type GetProperty<T extends string> =
328/// //  _ check_type
329///     T extends `${string}.${infer U}`  // <- extends_type
330///         ? U                           // <- true_type
331///         : never;                      // <- false_type
332/// ```
333///
334/// ## Reference
335/// * [TypeScript Handbook - Conditional Types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html)
336#[ast(visit)]
337#[scope(flags = ScopeFlags::TsConditional)]
338#[derive(Debug)]
339#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
340pub struct TSConditionalType<'a> {
341    pub span: Span,
342    /// The type before `extends` in the test expression.
343    pub check_type: TSType<'a>,
344    /// The type `check_type` is being tested against.
345    #[scope(enter_before)]
346    pub extends_type: TSType<'a>,
347    /// The type evaluated to if the test is true.
348    pub true_type: TSType<'a>,
349    /// The type evaluated to if the test is false.
350    #[scope(exit_before)]
351    pub false_type: TSType<'a>,
352    pub scope_id: Cell<Option<ScopeId>>,
353}
354
355/// TypeScript Union Type
356///
357/// ## Example
358/// ```ts
359///  string | string[] | (() => string) | { s: string }
360/// ```
361///
362/// ## Reference
363/// * [TypeScript Handbook - Union Types](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#unions)
364#[ast(visit)]
365#[derive(Debug)]
366#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
367pub struct TSUnionType<'a> {
368    pub span: Span,
369    /// The types in the union.
370    pub types: Vec<'a, TSType<'a>>,
371}
372
373/// TypeScript Intersection Type
374///
375/// ## Example
376/// ```ts
377/// type Colorful = { color: string };
378/// type Circle = { radius: number };
379///
380/// // `types` will be `[Colorful, Circle]`
381/// type ColorfulCircle = Colorful & Circle;
382/// ```
383///
384/// ## Reference
385/// * [TypeScript Handbook - Intersection Types](https://www.typescriptlang.org/docs/handbook/2/objects.html#intersection-types)
386#[ast(visit)]
387#[derive(Debug)]
388#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
389pub struct TSIntersectionType<'a> {
390    pub span: Span,
391    pub types: Vec<'a, TSType<'a>>,
392}
393
394/// Parenthesized Type
395///
396/// Like [`ParenthesizedExpression`], but for types.
397///
398/// ## Example
399/// ```ts
400/// type Foo = (string | number);
401/// //          ^^^^^^^^^^^^^^^^ type_annotation
402/// ```
403#[ast(visit)]
404#[derive(Debug)]
405#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
406#[estree(via = TSParenthesizedTypeConverter)]
407pub struct TSParenthesizedType<'a> {
408    pub span: Span,
409    pub type_annotation: TSType<'a>,
410}
411
412/// TypeScript Type Operators
413///
414/// Includes
415/// - `keyof`
416/// - `unique`
417/// - `readonly`
418///
419/// ## References
420/// * [TypeScript Handbook - Keyof Types](https://www.typescriptlang.org/docs/handbook/2/keyof-types.html)
421#[ast(visit)]
422#[derive(Debug)]
423#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
424pub struct TSTypeOperator<'a> {
425    pub span: Span,
426    pub operator: TSTypeOperatorOperator,
427    /// The type being operated on
428    pub type_annotation: TSType<'a>,
429}
430
431/// Operator in a [`TSTypeOperator`].
432#[ast]
433#[derive(Debug, Clone, Copy, PartialEq, Eq)]
434#[generate_derive(CloneIn, Dummy, ContentEq, ESTree)]
435pub enum TSTypeOperatorOperator {
436    Keyof = 0,
437    Unique = 1,
438    Readonly = 2,
439}
440
441/// TypeScript Array Type
442///
443/// Does not include tuple types, which are stored as [`TSTupleType`].
444///
445/// ## Example
446///
447/// ```ts
448/// let myArray: string[] = ["hello", "world"];
449/// ```
450///
451/// <https://www.typescriptlang.org/docs/handbook/2/objects.html#the-array-type>
452#[ast(visit)]
453#[derive(Debug)]
454#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
455pub struct TSArrayType<'a> {
456    pub span: Span,
457    pub element_type: TSType<'a>,
458}
459
460/// TypeScript Index Access Type
461///
462/// This is the type equivalent to expression member access.
463///
464/// ## Example
465///
466/// ```ts
467/// type I1 = Person["age" | "name"];
468/// ```
469///
470/// <https://www.typescriptlang.org/docs/handbook/2/indexed-access-types.html#handbook-content>
471#[ast(visit)]
472#[derive(Debug)]
473#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
474pub struct TSIndexedAccessType<'a> {
475    pub span: Span,
476    pub object_type: TSType<'a>,
477    pub index_type: TSType<'a>,
478}
479
480/// TypeScript Tuple Type
481///
482/// ## Example
483///
484/// ```ts
485/// type `StringNumberPair` = [string, number];
486/// ```
487///
488/// <https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types>
489#[ast(visit)]
490#[derive(Debug)]
491#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
492pub struct TSTupleType<'a> {
493    pub span: Span,
494    pub element_types: Vec<'a, TSTupleElement<'a>>,
495}
496
497/// TypeScript Named Tuple Member
498///
499/// ## Example
500/// ```ts
501/// type Foo = [first: string, second: number];
502/// //          ^^^^^^^^^^^^^ TSNamedTupleMember
503/// //    label ^^^^^  ^^^^^^ element_type
504/// ```
505///
506/// ## Reference
507/// * [TypeScript Handbook - Tuple Types](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types)
508#[ast(visit)]
509#[derive(Debug)]
510#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
511pub struct TSNamedTupleMember<'a> {
512    pub span: Span,
513    pub label: IdentifierName<'a>,
514    pub element_type: TSTupleElement<'a>,
515    pub optional: bool,
516}
517
518/// TypeScript Optional Type
519///
520/// Note that this does not cover optional object or class properties.
521///
522/// ## Example
523/// ```ts
524/// type Foo = [number?]
525/// //          ^^^^^^ type_annotation
526/// ```
527#[ast(visit)]
528#[derive(Debug)]
529#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
530pub struct TSOptionalType<'a> {
531    pub span: Span,
532    pub type_annotation: TSType<'a>,
533}
534
535/// TypeScript Rest Type
536///
537/// ## Example
538/// ```ts
539/// //                  ___________ this is the rest type
540/// type Foo = [number, ...string[]]
541/// //                     ^^^^^^^^ type_annotation
542/// ```
543#[ast(visit)]
544#[derive(Debug)]
545#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
546pub struct TSRestType<'a> {
547    pub span: Span,
548    pub type_annotation: TSType<'a>,
549}
550
551inherit_variants! {
552/// TS Tuple Element
553///
554/// Inherits variants from [`TSType`]. See [`ast` module docs] for explanation of inheritance.
555///
556/// See [`TSNamedTupleMember`] for named tuple elements.
557///
558/// [`ast` module docs]: `super`
559#[ast(visit)]
560#[derive(Debug)]
561#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ESTree)]
562pub enum TSTupleElement<'a> {
563    // Discriminants start at 64, so that `TSTupleElement::is_ts_type` is a single
564    // bitwise AND operation on the discriminant (`discriminant & 63 != 0`).
565    TSOptionalType(Box<'a, TSOptionalType<'a>>) = 64,
566    TSRestType(Box<'a, TSRestType<'a>>) = 65,
567    // `TSType` variants added here by `inherit_variants!` macro
568    @inherit TSType
569}
570}
571
572/// TypeScript `any` keyword
573///
574/// ## Example
575/// ```ts
576/// type Foo = any;
577/// ```
578///
579/// ## Reference
580/// * [TypeScript Handbook - Any Type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any)
581#[ast(visit)]
582#[derive(Debug)]
583#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
584pub struct TSAnyKeyword {
585    pub span: Span,
586}
587
588/// TypeScript `string` keyword
589///
590/// ## Example
591/// ```ts
592/// type Foo = string;
593/// ```
594///
595/// ## Reference
596/// * [TypeScript Handbook - Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#the-primitives-string-number-and-boolean)
597#[ast(visit)]
598#[derive(Debug)]
599#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
600pub struct TSStringKeyword {
601    pub span: Span,
602}
603
604/// TypeScript `boolean` keyword
605///
606/// ## Example
607/// ```ts
608/// type Foo = boolean;
609/// ```
610///
611/// ## Reference
612/// * [TypeScript Handbook - Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#the-primitives-string-number-and-boolean)
613#[ast(visit)]
614#[derive(Debug)]
615#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
616pub struct TSBooleanKeyword {
617    pub span: Span,
618}
619
620/// TypeScript `number` keyword
621///
622/// ## Example
623/// ```ts
624/// type Foo = boolean;
625/// ```
626///
627/// ## Reference
628/// * [TypeScript Handbook - Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#the-primitives-string-number-and-boolean)
629#[ast(visit)]
630#[derive(Debug)]
631#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
632pub struct TSNumberKeyword {
633    pub span: Span,
634}
635
636/// TypeScript `never` Keyword
637///
638/// ## Example
639/// ```ts
640/// type Foo<T> = T extends string ? never : T;
641/// //                               ^^^^^
642/// ```
643///
644/// ## Reference
645/// * [TypeScript Handbook - Advanced Topics](https://www.typescriptlang.org/docs/handbook/type-compatibility.html#advanced-topics)
646#[ast(visit)]
647#[derive(Debug)]
648#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
649pub struct TSNeverKeyword {
650    pub span: Span,
651}
652
653/// TypeScript `intrinsic` Keyword
654///
655/// Intrinsic types are built into TypeScript and are not user-defined.
656/// ## Example
657/// `type Uppercase<T extends character> = intrinsic;`
658///
659/// ### References
660/// * [TypeScript Handbook - Intrinsic String Manipulation
661/// Types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html#intrinsic-string-manipulation-types)
662/// * [microsoft/TypeScript #40580](https://github.com/microsoft/TypeScript/pull/40580)
663#[ast(visit)]
664#[derive(Debug)]
665#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
666pub struct TSIntrinsicKeyword {
667    pub span: Span,
668}
669
670/// TypeScript `unknown` Keyword
671///
672/// This is like `any`, but is not assignable to anything except `any` and `unknown`.
673///
674/// ## Example
675/// ```ts
676/// type Foo = unknown;
677/// ```
678///
679/// ## Reference
680/// * [TypeScript Handbook - Advanced Topics](https://www.typescriptlang.org/docs/handbook/type-compatibility.html#advanced-topics)
681#[ast(visit)]
682#[derive(Debug)]
683#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
684pub struct TSUnknownKeyword {
685    pub span: Span,
686}
687
688/// TypeScript `null` Keyword
689///
690/// ## Example
691/// ```ts
692/// type Foo = string | null;
693/// //                  ^^^^
694/// ```
695///
696/// ## Reference
697/// * [TypeScript Handbook - Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#null-and-undefined)
698#[ast(visit)]
699#[derive(Debug)]
700#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
701pub struct TSNullKeyword {
702    pub span: Span,
703}
704
705/// TypeScript `undefined` Keyword
706///
707/// ## Example
708/// ```ts
709/// type Foo = string | undefined;
710/// //                  ^^^^^^^^^
711/// ```
712///
713/// ## Reference
714/// * [TypeScript Handbook - Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#null-and-undefined)
715/// ## Reference
716/// * [TypeScript Handbook - Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#null-and-undefined)
717#[ast(visit)]
718#[derive(Debug)]
719#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
720pub struct TSUndefinedKeyword {
721    pub span: Span,
722}
723
724#[ast(visit)]
725#[derive(Debug)]
726#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
727pub struct TSVoidKeyword {
728    pub span: Span,
729}
730
731#[ast(visit)]
732#[derive(Debug)]
733#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
734pub struct TSSymbolKeyword {
735    pub span: Span,
736}
737
738#[ast(visit)]
739#[derive(Debug)]
740#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
741pub struct TSThisType {
742    pub span: Span,
743}
744
745#[ast(visit)]
746#[derive(Debug)]
747#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
748pub struct TSObjectKeyword {
749    pub span: Span,
750}
751
752#[ast(visit)]
753#[derive(Debug)]
754#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
755pub struct TSBigIntKeyword {
756    pub span: Span,
757}
758
759/// TypeScript Type Reference
760///
761/// ## Example
762/// ```ts
763/// type A = X;
764/// //       ^
765/// type B = Y.a;
766/// //       ^^^
767/// type C<T> = Z.b<T>;
768/// //          ^^^^^^
769/// ```
770#[ast(visit)]
771#[derive(Debug)]
772#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
773pub struct TSTypeReference<'a> {
774    pub span: Span,
775    pub type_name: TSTypeName<'a>,
776    pub type_arguments: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
777}
778
779/// TSTypeName:
780///     IdentifierReference
781///     this
782///     TSTypeName . IdentifierName
783#[ast(visit)]
784#[derive(Debug)]
785#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ESTree)]
786pub enum TSTypeName<'a> {
787    IdentifierReference(Box<'a, IdentifierReference<'a>>) = 0,
788    QualifiedName(Box<'a, TSQualifiedName<'a>>) = 1,
789    ThisExpression(Box<'a, ThisExpression>) = 2,
790}
791
792/// Macro for matching `TSTypeName`'s variants.
793#[macro_export]
794macro_rules! match_ts_type_name {
795    ($ty:ident) => {
796        $ty::IdentifierReference(_) | $ty::QualifiedName(_) | $ty::ThisExpression(_)
797    };
798}
799pub use match_ts_type_name;
800
801/// TypeScript Qualified Name
802///
803/// A [type reference](TSTypeReference) qualified by a namespace.
804///
805/// ## Example
806/// ```ts
807/// type Foo = A.B.C;
808/// //         ^^^^^
809/// ```
810#[ast(visit)]
811#[derive(Debug)]
812#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
813pub struct TSQualifiedName<'a> {
814    pub span: Span,
815    pub left: TSTypeName<'a>,
816    pub right: IdentifierName<'a>,
817}
818
819#[ast(visit)]
820#[derive(Debug)]
821#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
822pub struct TSTypeParameterInstantiation<'a> {
823    pub span: Span,
824    pub params: Vec<'a, TSType<'a>>,
825}
826
827/// TypeScript Type Parameter
828///
829/// This is a type parameter in a generic type or function.
830///
831/// ## Example
832/// ```ts
833/// //                 ______ constraint
834/// type Box<T extends string = 'foo'> = { value: T };
835/// // name  ^                  ^^^^^ default
836///
837/// function add<in T>(a: T, b: T): T { return a + b; }
838/// //           ^^ in: true
839/// ```
840///
841/// ## References
842/// * [TypeScript Handbook - Generics](https://www.typescriptlang.org/docs/handbook/2/generics.html)
843/// * [TypeScript Handbook - Variance Annotations](https://www.typescriptlang.org/docs/handbook/2/generics.html#variance-annotations)
844#[ast(visit)]
845#[derive(Debug)]
846#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
847pub struct TSTypeParameter<'a> {
848    pub span: Span,
849    /// The name of the parameter, e.g. `T` in `type Foo<T> = ...`.
850    pub name: BindingIdentifier<'a>,
851    /// Constrains what types can be passed to the type parameter.
852    pub constraint: Option<TSType<'a>>,
853    /// Default value of the type parameter if no type is provided when using the type.
854    pub default: Option<TSType<'a>>,
855    /// Was an `in` modifier keyword present?
856    pub r#in: bool,
857    /// Was an `out` modifier keyword present?
858    pub out: bool,
859    /// Was a `const` modifier keyword present?
860    pub r#const: bool,
861}
862
863#[ast(visit)]
864#[derive(Debug)]
865#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
866pub struct TSTypeParameterDeclaration<'a> {
867    pub span: Span,
868    pub params: Vec<'a, TSTypeParameter<'a>>,
869}
870
871/// TypeScript Type Alias Declaration Statement
872///
873/// ## Example
874/// ```ts
875/// //   _____ id
876/// type Maybe<T> = T | null | undefined;
877/// //         ^ type_parameters
878/// ```
879#[ast(visit)]
880#[scope]
881#[derive(Debug)]
882#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
883pub struct TSTypeAliasDeclaration<'a> {
884    pub span: Span,
885    /// Type alias's identifier, e.g. `Foo` in `type Foo = number`.
886    pub id: BindingIdentifier<'a>,
887    #[scope(enter_before)]
888    pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
889    pub type_annotation: TSType<'a>,
890    pub declare: bool,
891    pub scope_id: Cell<Option<ScopeId>>,
892}
893
894#[ast]
895#[derive(Debug, Clone, Copy, PartialEq, Eq)]
896#[generate_derive(CloneIn, Dummy, ContentEq, ESTree)]
897pub enum TSAccessibility {
898    Private = 0,
899    Protected = 1,
900    Public = 2,
901}
902
903/// TypeScript Class Interface Heritage
904///
905/// `implements` clause of a [class declaration](Class).
906///
907/// ## Example
908/// ```ts
909/// //                   ___ expression
910/// class Foo implements Bar, Baz<number, string> {}
911/// //            type_arguments ^^^^^^^^^^^^^^
912/// ```
913#[ast(visit)]
914#[derive(Debug)]
915#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
916#[plural(TSClassImplementsList)]
917pub struct TSClassImplements<'a> {
918    pub span: Span,
919    #[estree(via = TSClassImplementsExpression)]
920    pub expression: TSTypeName<'a>,
921    pub type_arguments: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
922}
923
924/// TypeScriptInterface Declaration
925///
926///   interface `BindingIdentifier` `TypeParameters_opt` `InterfaceExtendsClause_opt` `ObjectType`
927///
928/// ## Example
929/// ```ts
930/// //                       ___ extends
931/// interface Foo<T> extends Bar {
932/// //     id ^^^ ^ type_parameters
933/// }
934/// ```
935///
936/// ## References
937/// * [TypeScript in 5 Minutes - Interfaces](https://www.typescriptlang.org/docs/handbook/typescript-tooling-in-5-minutes.html#interfaces)
938/// * [TypeScript Handbook - Interfaces](https://www.typescriptlang.org/docs/handbook/2/objects.html#interfaces)
939#[ast(visit)]
940#[scope]
941#[derive(Debug)]
942#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
943pub struct TSInterfaceDeclaration<'a> {
944    pub span: Span,
945    /// The identifier (name) of the interface.
946    pub id: BindingIdentifier<'a>,
947    /// Type parameters that get bound to the interface.
948    #[scope(enter_before)]
949    pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
950    /// Other interfaces/types this interface extends.
951    pub extends: Vec<'a, TSInterfaceHeritage<'a>>,
952    pub body: Box<'a, TSInterfaceBody<'a>>,
953    /// `true` for `declare interface Foo {}`
954    pub declare: bool,
955    pub scope_id: Cell<Option<ScopeId>>,
956}
957
958/// Body of a [`TSInterfaceDeclaration`].
959#[ast(visit)]
960#[derive(Debug)]
961#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
962pub struct TSInterfaceBody<'a> {
963    pub span: Span,
964    pub body: Vec<'a, TSSignature<'a>>,
965}
966
967/// TypeScript Property Signature
968///
969/// Used in [classes](Class), [interfaces](TSInterfaceDeclaration), [mapped types](TSMappedType),
970/// etc. Part of a [`TSSignature`].
971///
972/// ## Example
973/// ```ts
974/// interface Foo {
975/// //  ___ key
976///     bar: number
977/// //     ^^^^^^^^ type_annotation
978///     baz?: string           // <- optional
979///     readonly bang: boolean // <- readonly
980/// }
981/// ```
982#[ast(visit)]
983#[derive(Debug)]
984#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
985#[estree(add_fields(accessibility = Null, r#static = False))]
986pub struct TSPropertySignature<'a> {
987    pub span: Span,
988    pub computed: bool,
989    pub optional: bool,
990    pub readonly: bool,
991    pub key: PropertyKey<'a>,
992    pub type_annotation: Option<Box<'a, TSTypeAnnotation<'a>>>,
993}
994
995#[ast(visit)]
996#[derive(Debug)]
997#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ESTree)]
998pub enum TSSignature<'a> {
999    TSIndexSignature(Box<'a, TSIndexSignature<'a>>) = 0,
1000    TSPropertySignature(Box<'a, TSPropertySignature<'a>>) = 1,
1001    TSCallSignatureDeclaration(Box<'a, TSCallSignatureDeclaration<'a>>) = 2,
1002    TSConstructSignatureDeclaration(Box<'a, TSConstructSignatureDeclaration<'a>>) = 3,
1003    TSMethodSignature(Box<'a, TSMethodSignature<'a>>) = 4,
1004}
1005
1006/// An index signature within a class, type alias, etc.
1007///
1008/// ## Example
1009/// [playground link](https://oxc-playground.netlify.app/?code=3YCAAIC9gICAgICAgIC6nsrEgtem3AB/pQsrWlLnujiFhkHVtfeFMq5RMD7X5AzJnZ5R/ecQ5KG1FUFjzXvrxFXH0m6HpS+Ob3TC8gQXeRQygA%3D%3D)
1010/// ```ts
1011/// type MapOf<T> = {
1012/// //   _________ parameters (vec with 1 element)
1013///     [K: string]: T
1014/// //               - type_annotation
1015/// }
1016/// ```
1017#[ast(visit)]
1018#[derive(Debug)]
1019#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1020#[estree(add_fields(accessibility = Null))]
1021pub struct TSIndexSignature<'a> {
1022    pub span: Span,
1023    pub parameters: Vec<'a, TSIndexSignatureName<'a>>,
1024    pub type_annotation: Box<'a, TSTypeAnnotation<'a>>,
1025    pub readonly: bool,
1026    pub r#static: bool,
1027}
1028
1029#[ast(visit)]
1030#[derive(Debug)]
1031#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1032pub struct TSCallSignatureDeclaration<'a> {
1033    pub span: Span,
1034    pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
1035    #[estree(skip)]
1036    pub this_param: Option<Box<'a, TSThisParameter<'a>>>,
1037    #[estree(via = TSCallSignatureDeclarationParams)]
1038    pub params: Box<'a, FormalParameters<'a>>,
1039    pub return_type: Option<Box<'a, TSTypeAnnotation<'a>>>,
1040}
1041
1042#[ast]
1043#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1044#[generate_derive(CloneIn, Dummy, ContentEq, ESTree)]
1045pub enum TSMethodSignatureKind {
1046    Method = 0,
1047    Get = 1,
1048    Set = 2,
1049}
1050
1051/// TypeScript Method Signature
1052///
1053/// Similar to a [`TSFunctionType`], but only for method shorthand syntax.
1054///
1055/// ## Example
1056/// ```ts
1057/// interface Foo {
1058///     bar(a: number): string;
1059/// //  ^^^ key
1060/// }
1061/// ```
1062#[ast(visit)]
1063#[scope]
1064#[derive(Debug)]
1065#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1066#[estree(add_fields(accessibility = Null, readonly = False, r#static = False))]
1067pub struct TSMethodSignature<'a> {
1068    pub span: Span,
1069    pub key: PropertyKey<'a>,
1070    pub computed: bool,
1071    pub optional: bool,
1072    pub kind: TSMethodSignatureKind,
1073    pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
1074    #[estree(skip)]
1075    pub this_param: Option<Box<'a, TSThisParameter<'a>>>,
1076    #[estree(via = TSMethodSignatureParams)]
1077    pub params: Box<'a, FormalParameters<'a>>,
1078    pub return_type: Option<Box<'a, TSTypeAnnotation<'a>>>,
1079    pub scope_id: Cell<Option<ScopeId>>,
1080}
1081
1082/// TypeScript Constructor Signature Declaration
1083#[ast(visit)]
1084#[scope]
1085#[derive(Debug)]
1086#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1087pub struct TSConstructSignatureDeclaration<'a> {
1088    pub span: Span,
1089    pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
1090    pub params: Box<'a, FormalParameters<'a>>,
1091    pub return_type: Option<Box<'a, TSTypeAnnotation<'a>>>,
1092    pub scope_id: Cell<Option<ScopeId>>,
1093}
1094
1095#[ast(visit)]
1096#[derive(Debug)]
1097#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1098#[estree(
1099    rename = "Identifier",
1100    add_fields(decorators = EmptyArray, optional = False),
1101    field_order(decorators, name, optional, type_annotation, span),
1102)]
1103pub struct TSIndexSignatureName<'a> {
1104    pub span: Span,
1105    #[estree(json_safe)]
1106    pub name: Atom<'a>,
1107    pub type_annotation: Box<'a, TSTypeAnnotation<'a>>,
1108}
1109
1110#[ast(visit)]
1111#[derive(Debug)]
1112#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1113pub struct TSInterfaceHeritage<'a> {
1114    pub span: Span,
1115    pub expression: Expression<'a>,
1116    pub type_arguments: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
1117}
1118
1119/// TypeScript Type Predicate
1120///
1121/// ## Examples
1122/// ```ts
1123/// function isString(x: unknown): x is string {
1124/// //              parameter_name ^    ^^^^^^ type_annotation
1125///     return typeof x === 'string';
1126/// }
1127/// ```
1128///
1129/// ```ts
1130/// function assertString(x: unknown): asserts x is string {
1131/// //                                 ^^^^^^^ asserts: true
1132///     if (typeof x !== 'string') throw new TypeError('x is not a string');
1133/// }
1134/// ```
1135///
1136/// ## References
1137/// * [TypeScript Handbook - Type Predicates](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates)
1138/// * [TypeScript Handbook - Assertion Functions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions)
1139#[ast(visit)]
1140#[derive(Debug)]
1141#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1142pub struct TSTypePredicate<'a> {
1143    pub span: Span,
1144    /// The identifier the predicate operates on
1145    pub parameter_name: TSTypePredicateName<'a>,
1146    /// Does this predicate include an `asserts` modifier?
1147    ///
1148    /// ## Example
1149    /// ```ts
1150    /// declare function isString(x: any): asserts x is string; // true
1151    /// ```
1152    pub asserts: bool,
1153    pub type_annotation: Option<Box<'a, TSTypeAnnotation<'a>>>,
1154}
1155
1156#[ast(visit)]
1157#[derive(Debug)]
1158#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1159pub enum TSTypePredicateName<'a> {
1160    Identifier(Box<'a, IdentifierName<'a>>) = 0,
1161    This(TSThisType) = 1,
1162}
1163
1164/// TypeScript Module and Namespace Declarations
1165///
1166/// ## Examples
1167/// ```ts
1168/// declare module 'foo' {
1169/// // kind ^^^^^^ ^^^^^ id
1170/// }
1171/// ```
1172///
1173/// ```ts
1174/// namespace Foo { }
1175/// declare namespace Bar { }
1176/// ```
1177///
1178/// ```ts
1179/// declare global {
1180///     interface Window {
1181///        customProp: string;
1182///     }
1183/// }
1184/// ```
1185///
1186/// ## References
1187/// * [TypeScript Handbook - Namespaces](https://www.typescriptlang.org/docs/handbook/2/modules.html#namespaces)
1188/// * [TypeScript Handbook - Module Augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)
1189/// * [TypeScript Handbook - Global Augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation)
1190#[ast(visit)]
1191#[scope(
1192    flags = ScopeFlags::TsModuleBlock,
1193    strict_if = self.body.as_ref().is_some_and(TSModuleDeclarationBody::has_use_strict_directive),
1194)]
1195#[derive(Debug)]
1196#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1197#[estree(
1198    via = TSModuleDeclarationConverter,
1199    add_fields(global = TSModuleDeclarationGlobal),
1200)]
1201pub struct TSModuleDeclaration<'a> {
1202    pub span: Span,
1203    /// The name of the module/namespace being declared.
1204    ///
1205    /// Note that for `declare global {}`, no symbol will be created for the module name.
1206    #[estree(ts_type = "BindingIdentifier | StringLiteral | TSQualifiedName")]
1207    pub id: TSModuleDeclarationName<'a>,
1208    #[scope(enter_before)]
1209    #[estree(ts_type = "TSModuleBlock | null")]
1210    pub body: Option<TSModuleDeclarationBody<'a>>,
1211    /// The keyword used to define this module declaration.
1212    ///
1213    /// Helps discriminate between global overrides vs module declarations vs namespace
1214    /// declarations.
1215    ///
1216    /// ```ts
1217    /// namespace Foo {}
1218    /// ^^^^^^^^^
1219    /// module 'foo' {}
1220    /// ^^^^^^
1221    /// declare global {}
1222    ///         ^^^^^^
1223    /// ```
1224    pub kind: TSModuleDeclarationKind,
1225    pub declare: bool,
1226    pub scope_id: Cell<Option<ScopeId>>,
1227}
1228
1229#[ast]
1230#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1231#[generate_derive(CloneIn, Dummy, ContentEq, ESTree)]
1232pub enum TSModuleDeclarationKind {
1233    /// `declare global {}`
1234    Global = 0,
1235    /// `declare module 'foo' {}`
1236    Module = 1,
1237    /// `namespace Foo {}`
1238    Namespace = 2,
1239}
1240
1241/// The name of a TypeScript [namespace or module declaration](TSModuleDeclaration).
1242///
1243/// Note that it is a syntax error for namespace declarations to have a string literal name.
1244/// Modules may have either kind.
1245///
1246/// ## Examples
1247/// ```ts
1248/// // TSModuleDeclarationName::StringLiteral
1249/// declare module "*.css" {
1250///     const styles: { [key: string]: string };
1251///     export default styles;
1252/// }
1253/// ```
1254///
1255/// ```ts
1256/// // TSModuleDeclarationName::Identifier
1257/// namespace Foo {
1258///    export const bar = 42;
1259/// }
1260/// ```
1261#[ast(visit)]
1262#[derive(Debug)]
1263#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1264#[estree(no_ts_def)]
1265pub enum TSModuleDeclarationName<'a> {
1266    Identifier(BindingIdentifier<'a>) = 0,
1267    StringLiteral(StringLiteral<'a>) = 1,
1268}
1269
1270#[ast(visit)]
1271#[derive(Debug)]
1272#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ESTree)]
1273#[estree(no_ts_def)]
1274pub enum TSModuleDeclarationBody<'a> {
1275    TSModuleDeclaration(Box<'a, TSModuleDeclaration<'a>>) = 0,
1276    TSModuleBlock(Box<'a, TSModuleBlock<'a>>) = 1,
1277}
1278
1279#[ast(visit)]
1280#[derive(Debug)]
1281#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1282pub struct TSModuleBlock<'a> {
1283    pub span: Span,
1284    #[estree(prepend_to = body)]
1285    pub directives: Vec<'a, Directive<'a>>,
1286    pub body: Vec<'a, Statement<'a>>,
1287}
1288
1289#[ast(visit)]
1290#[derive(Debug)]
1291#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1292pub struct TSTypeLiteral<'a> {
1293    pub span: Span,
1294    pub members: Vec<'a, TSSignature<'a>>,
1295}
1296
1297/// TypeScript `infer` type
1298///
1299/// Used in a [`TSConditionalType`] to bind a type parameter when some tested type extends a
1300/// desired type.
1301///
1302/// ## Example
1303/// ```ts
1304/// type Foo<T> = T extends infer U ? U : never;
1305/// //                            ^ type_parameter
1306/// ```
1307///
1308/// ## Reference
1309/// * [TypeScript Handbook - Inferring With Conditional Types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#inferring-within-conditional-types)
1310#[ast(visit)]
1311#[derive(Debug)]
1312#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1313pub struct TSInferType<'a> {
1314    pub span: Span,
1315    /// The type bound when the
1316    pub type_parameter: Box<'a, TSTypeParameter<'a>>,
1317}
1318
1319/// Type Query
1320///
1321/// ## Example
1322/// ```ts
1323/// type Foo = typeof Bar;
1324/// ```
1325///
1326/// ## Reference
1327/// * [TypeScript Handbook - Typeof Type Operator](https://www.typescriptlang.org/docs/handbook/2/typeof-types.html)
1328#[ast(visit)]
1329#[derive(Debug)]
1330#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1331pub struct TSTypeQuery<'a> {
1332    pub span: Span,
1333    pub expr_name: TSTypeQueryExprName<'a>,
1334    pub type_arguments: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
1335}
1336
1337inherit_variants! {
1338/// TS Type Query Expr Name
1339///
1340/// Inherits variants from [`TSTypeName`]. See [`ast` module docs] for explanation of inheritance.
1341///
1342/// [`ast` module docs]: `super`
1343#[ast(visit)]
1344#[derive(Debug)]
1345#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ESTree)]
1346pub enum TSTypeQueryExprName<'a> {
1347    /// `type foo = typeof import('foo')`
1348    TSImportType(Box<'a, TSImportType<'a>>) = 3,
1349    // `TSTypeName` variants added here by `inherit_variants!` macro
1350    @inherit TSTypeName
1351}
1352}
1353
1354/// `import('foo')` in `type Foo = import('foo');`
1355///
1356/// ```ts
1357/// //                       ______________ options
1358/// type Foo = import('foo', { assert: {} })<T>;
1359/// //                ^^^^^ argument        ^^^ type_arguments
1360///
1361/// type Foo = import('foo').bar;
1362/// //                       ^^^ qualifier
1363/// ```
1364#[ast(visit)]
1365#[derive(Debug)]
1366#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1367pub struct TSImportType<'a> {
1368    pub span: Span,
1369    pub argument: TSType<'a>,
1370    pub options: Option<Box<'a, ObjectExpression<'a>>>,
1371    pub qualifier: Option<TSImportTypeQualifier<'a>>,
1372    pub type_arguments: Option<Box<'a, TSTypeParameterInstantiation<'a>>>,
1373}
1374
1375/// TypeScript Import Type Qualifier
1376///
1377/// The qualifier part of an import type that doesn't create references.
1378/// In `import("./a").b.c`, the `.b.c` part is the qualifier.
1379///
1380/// Unlike `TSTypeName`, this doesn't use `IdentifierReference` because
1381/// these are not references to identifiers in scope, but rather property
1382/// accesses on the imported module type.
1383#[ast(visit)]
1384#[derive(Debug)]
1385#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ESTree)]
1386pub enum TSImportTypeQualifier<'a> {
1387    Identifier(Box<'a, IdentifierName<'a>>) = 0,
1388    QualifiedName(Box<'a, TSImportTypeQualifiedName<'a>>) = 1,
1389}
1390
1391/// TypeScript Import Type Qualified Name
1392///
1393/// A qualified name in an import type (e.g., `a.b.c` in `import("./module").a.b.c`)
1394#[ast(visit)]
1395#[derive(Debug)]
1396#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1397#[estree(rename = "TSQualifiedName")]
1398pub struct TSImportTypeQualifiedName<'a> {
1399    pub span: Span,
1400    pub left: TSImportTypeQualifier<'a>,
1401    pub right: IdentifierName<'a>,
1402}
1403
1404/// TypeScript Function Type
1405///
1406/// ## Examples
1407/// ```ts
1408/// //       __________ this is the TSFunctionType
1409/// type T = () => void
1410/// //             ^^^^ return_type
1411/// ```
1412#[ast(visit)]
1413#[scope]
1414#[derive(Debug)]
1415#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1416pub struct TSFunctionType<'a> {
1417    pub span: Span,
1418    /// Generic type parameters
1419    ///
1420    /// ```ts
1421    /// type T = <U>(x: U) => U;
1422    /// //        ^
1423    /// ```
1424    pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
1425    /// `this` parameter
1426    ///
1427    /// ```ts
1428    /// type T = (this: string, a: number) => void;
1429    /// //        ^^^^^^^^^^^^
1430    /// ```
1431    #[estree(skip)]
1432    pub this_param: Option<Box<'a, TSThisParameter<'a>>>,
1433    /// Function parameters. Akin to [`Function::params`].
1434    #[estree(via = TSFunctionTypeParams)]
1435    pub params: Box<'a, FormalParameters<'a>>,
1436    /// Return type of the function.
1437    /// ```ts
1438    /// type T = () => void;
1439    /// //             ^^^^
1440    /// ```
1441    pub return_type: Box<'a, TSTypeAnnotation<'a>>,
1442
1443    pub scope_id: Cell<Option<ScopeId>>,
1444}
1445
1446#[ast(visit)]
1447#[derive(Debug)]
1448#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1449pub struct TSConstructorType<'a> {
1450    pub span: Span,
1451    pub r#abstract: bool,
1452    pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
1453    pub params: Box<'a, FormalParameters<'a>>,
1454    pub return_type: Box<'a, TSTypeAnnotation<'a>>,
1455}
1456
1457/// TypeScript Mapped Type
1458///
1459/// ## Examples
1460/// ```ts
1461/// type Maybe<T> = {
1462/// //        _____ constraint
1463///     [P in keyof T]?: T[P]
1464/// //   ^ type_parameter
1465/// }
1466/// ```
1467///
1468/// ```ts
1469/// type ReadonlyDefinite<T> = {
1470/// //           _ type parameter
1471///    readonly [P in keyof T]-?: T[P]
1472/// //                        ^^ `optional` modifier
1473/// };
1474/// ```
1475///
1476/// ## References
1477/// * [TypeScript Handbook - Mapped Types](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html)
1478#[ast(visit)]
1479#[scope]
1480#[derive(Debug)]
1481#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1482#[estree(
1483    add_fields(key = TSMappedTypeKey, constraint = TSMappedTypeConstraint),
1484    field_order(key, constraint, name_type, type_annotation, optional, readonly, span),
1485)]
1486pub struct TSMappedType<'a> {
1487    pub span: Span,
1488    /// Key type parameter, e.g. `P` in `[P in keyof T]`.
1489    #[estree(skip)]
1490    pub type_parameter: Box<'a, TSTypeParameter<'a>>,
1491    pub name_type: Option<TSType<'a>>,
1492    pub type_annotation: Option<TSType<'a>>,
1493    /// Optional modifier on type annotation
1494    ///
1495    /// ## Examples
1496    /// ```ts
1497    /// type Foo = { [P in keyof T]?: T[P] }
1498    /// //                         ^  Some(True)
1499    /// type Bar = { [P in keyof T]+?: T[P] }
1500    /// //                         ^^ Some(Plus)
1501    /// type Baz = { [P in keyof T]-?: T[P] }
1502    /// //                         ^^ Some(Minus)
1503    /// type Qux = { [P in keyof T]: T[P] }
1504    /// //                         ^  None
1505    /// ```
1506    #[estree(via = TSMappedTypeOptional)]
1507    pub optional: Option<TSMappedTypeModifierOperator>,
1508    /// Readonly modifier before keyed index signature
1509    ///
1510    /// ## Examples
1511    /// ```ts
1512    /// type Foo = { readonly [P in keyof T]: T[P] }  // Some(True)
1513    /// type Bar = { +readonly [P in keyof T]: T[P] } // Some(Plus)
1514    /// type Baz = { -readonly [P in keyof T]: T[P] } // Some(Minus)
1515    /// type Qux = { [P in keyof T]: T[P] }           // None
1516    /// ```
1517    pub readonly: Option<TSMappedTypeModifierOperator>,
1518    pub scope_id: Cell<Option<ScopeId>>,
1519}
1520
1521#[ast]
1522#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1523#[generate_derive(CloneIn, Dummy, ContentEq, ESTree)]
1524pub enum TSMappedTypeModifierOperator {
1525    /// e.g. `?` in `{ [P in K]?: T }`
1526    #[estree(via = True)]
1527    True = 0,
1528    /// e.g. `+?` in `{ [P in K]+?: T }`
1529    #[estree(rename = "+")]
1530    Plus = 1,
1531    /// e.g. `-?` in `{ [P in K]-?: T }`
1532    #[estree(rename = "-")]
1533    Minus = 2,
1534}
1535
1536/// TypeScript Template Literal Type
1537///
1538/// ## Example
1539/// ```ts
1540/// // Each string part is an element in `quasis`, including empty strings at the beginning/end.
1541/// // In this example, `quasis` has 3 elements: ["", ".", ""]
1542/// type Dot<T, U> = `${T}.${U}`;
1543/// ```
1544///
1545/// ## Reference
1546/// * [TypeScript Handbook - Template Literal Types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html#handbook-content)
1547#[ast(visit)]
1548#[derive(Debug)]
1549#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1550pub struct TSTemplateLiteralType<'a> {
1551    pub span: Span,
1552    /// The string parts of the template literal.
1553    pub quasis: Vec<'a, TemplateElement<'a>>,
1554    /// The interpolated expressions in the template literal.
1555    pub types: Vec<'a, TSType<'a>>,
1556}
1557
1558#[ast(visit)]
1559#[derive(Debug)]
1560#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1561pub struct TSAsExpression<'a> {
1562    pub span: Span,
1563    pub expression: Expression<'a>,
1564    pub type_annotation: TSType<'a>,
1565}
1566
1567/// TypeScript `satisfies` Expression
1568///
1569/// ## Example
1570/// ```ts
1571/// const user = {
1572///     id: 0,
1573///     name: 'Alice',
1574/// } satisfies User;
1575/// ```
1576///
1577/// ## Reference
1578/// * [TypeScript Handbook - The `satisfies` Operator](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html#the-satisfies-operator)
1579#[ast(visit)]
1580#[derive(Debug)]
1581#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1582pub struct TSSatisfiesExpression<'a> {
1583    pub span: Span,
1584    /// The value expression being constrained.
1585    pub expression: Expression<'a>,
1586    /// The type `expression` must satisfy.
1587    pub type_annotation: TSType<'a>,
1588}
1589
1590/// TypeScript Type Assertion
1591///
1592/// ## Example
1593/// ```ts
1594/// //                ___ expression
1595/// let foo = <number>bar;
1596/// //        ^^^^^^^^ type_annotation
1597/// ```
1598#[ast(visit)]
1599#[derive(Debug)]
1600#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1601pub struct TSTypeAssertion<'a> {
1602    pub span: Span,
1603    pub type_annotation: TSType<'a>,
1604    pub expression: Expression<'a>,
1605}
1606
1607#[ast(visit)]
1608#[derive(Debug)]
1609#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1610pub struct TSImportEqualsDeclaration<'a> {
1611    pub span: Span,
1612    pub id: BindingIdentifier<'a>,
1613    pub module_reference: TSModuleReference<'a>,
1614    pub import_kind: ImportOrExportKind,
1615}
1616
1617inherit_variants! {
1618/// TS Module Reference
1619///
1620/// Inherits variants from [`TSTypeName`]. See [`ast` module docs] for explanation of inheritance.
1621///
1622/// [`ast` module docs]: `super`
1623#[ast(visit)]
1624#[derive(Debug)]
1625#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ESTree)]
1626pub enum TSModuleReference<'a> {
1627    ExternalModuleReference(Box<'a, TSExternalModuleReference<'a>>) = 3,
1628    // `TSTypeName` variants added here by `inherit_variants!` macro
1629    @inherit TSTypeName
1630}
1631}
1632
1633#[ast(visit)]
1634#[derive(Debug)]
1635#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1636pub struct TSExternalModuleReference<'a> {
1637    pub span: Span,
1638    pub expression: StringLiteral<'a>,
1639}
1640
1641#[ast(visit)]
1642#[derive(Debug)]
1643#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1644pub struct TSNonNullExpression<'a> {
1645    pub span: Span,
1646    pub expression: Expression<'a>,
1647}
1648
1649/// Decorator
1650///
1651/// Decorators are annotations on classes, methods, properties, and parameters.
1652/// They are usually either an [`IdentifierReference`] or an [`CallExpression`].
1653///
1654/// ## Example
1655/// ```ts
1656/// @Foo                        // class decorator
1657/// @Bar()                      // class decorator factory
1658/// class SomeClass {
1659///     @Freeze                 // property decorator
1660///     public x: number;
1661///
1662///     @MethodDecorator        // method decorator
1663///     public method(
1664///         @LogParam x: number // parameter decorator
1665///     ) {
1666///       // ...
1667///     }
1668/// }
1669/// ```
1670///
1671/// [`IdentifierReference`]: crate::ast::js::IdentifierReference
1672/// [`CallExpression`]: crate::ast::js::CallExpression
1673#[ast(visit)]
1674#[derive(Debug)]
1675#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1676pub struct Decorator<'a> {
1677    pub span: Span,
1678    pub expression: Expression<'a>,
1679}
1680
1681/// Export Assignment in non-module files
1682///
1683/// `export = foo`
1684#[ast(visit)]
1685#[derive(Debug)]
1686#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1687pub struct TSExportAssignment<'a> {
1688    pub span: Span,
1689    pub expression: Expression<'a>,
1690}
1691
1692/// Namespace Export Declaration in declaration files
1693///
1694/// `export as namespace foo`
1695#[ast(visit)]
1696#[derive(Debug)]
1697#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1698pub struct TSNamespaceExportDeclaration<'a> {
1699    pub span: Span,
1700    pub id: IdentifierName<'a>,
1701}
1702
1703#[ast(visit)]
1704#[derive(Debug)]
1705#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1706pub struct TSInstantiationExpression<'a> {
1707    pub span: Span,
1708    pub expression: Expression<'a>,
1709    pub type_arguments: Box<'a, TSTypeParameterInstantiation<'a>>,
1710}
1711
1712/// See [TypeScript - Type-Only Imports and Exports](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html)
1713#[ast]
1714#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1715#[generate_derive(CloneIn, Dummy, ContentEq, ESTree)]
1716pub enum ImportOrExportKind {
1717    /// `import { foo } from './foo'`;
1718    Value = 0,
1719    /// `import type { foo } from './foo'`;
1720    Type = 1,
1721}
1722
1723// [`JSDoc`](https://github.com/microsoft/TypeScript/blob/54a554d8af2657630307cbfa8a3e4f3946e36507/src/compiler/types.ts#L393)
1724
1725/// `type foo = ty?` or `type foo = ?ty`
1726#[ast(visit)]
1727#[derive(Debug)]
1728#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1729#[estree(rename = "TSJSDocNullableType")]
1730pub struct JSDocNullableType<'a> {
1731    pub span: Span,
1732    pub type_annotation: TSType<'a>,
1733    /// Was `?` after the type annotation?
1734    pub postfix: bool,
1735}
1736
1737/// `type foo = ty!` or `type foo = !ty`
1738#[ast(visit)]
1739#[derive(Debug)]
1740#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1741#[estree(rename = "TSJSDocNonNullableType")]
1742pub struct JSDocNonNullableType<'a> {
1743    pub span: Span,
1744    pub type_annotation: TSType<'a>,
1745    pub postfix: bool,
1746}
1747
1748/// `type T = (?)`
1749#[ast(visit)]
1750#[derive(Debug)]
1751#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
1752#[estree(rename = "TSJSDocUnknownType")]
1753pub struct JSDocUnknownType {
1754    pub span: Span,
1755}