diff --git a/crates/rome_js_factory/src/generated/node_factory.rs b/crates/rome_js_factory/src/generated/node_factory.rs index dfc854747c4..684f43af0b4 100644 --- a/crates/rome_js_factory/src/generated/node_factory.rs +++ b/crates/rome_js_factory/src/generated/node_factory.rs @@ -4980,14 +4980,34 @@ pub fn ts_indexed_access_type( ], )) } -pub fn ts_infer_type(infer_token: SyntaxToken, type_parameter: TsTypeParameterName) -> TsInferType { - TsInferType::unwrap_cast(SyntaxNode::new_detached( - JsSyntaxKind::TS_INFER_TYPE, - [ - Some(SyntaxElement::Token(infer_token)), - Some(SyntaxElement::Node(type_parameter.into_syntax())), - ], - )) +pub fn ts_infer_type(infer_token: SyntaxToken, name: TsTypeParameterName) -> TsInferTypeBuilder { + TsInferTypeBuilder { + infer_token, + name, + constraint: None, + } +} +pub struct TsInferTypeBuilder { + infer_token: SyntaxToken, + name: TsTypeParameterName, + constraint: Option, +} +impl TsInferTypeBuilder { + pub fn with_constraint(mut self, constraint: TsTypeConstraintClause) -> Self { + self.constraint = Some(constraint); + self + } + pub fn build(self) -> TsInferType { + TsInferType::unwrap_cast(SyntaxNode::new_detached( + JsSyntaxKind::TS_INFER_TYPE, + [ + Some(SyntaxElement::Token(self.infer_token)), + Some(SyntaxElement::Node(self.name.into_syntax())), + self.constraint + .map(|token| SyntaxElement::Node(token.into_syntax())), + ], + )) + } } pub fn ts_instantiation_expression( expression: AnyJsExpression, diff --git a/crates/rome_js_factory/src/generated/syntax_factory.rs b/crates/rome_js_factory/src/generated/syntax_factory.rs index fc445f48bdc..bcdc97cc87b 100644 --- a/crates/rome_js_factory/src/generated/syntax_factory.rs +++ b/crates/rome_js_factory/src/generated/syntax_factory.rs @@ -7597,7 +7597,7 @@ impl SyntaxFactory for JsSyntaxFactory { } TS_INFER_TYPE => { let mut elements = (&children).into_iter(); - let mut slots: RawNodeSlots<2usize> = RawNodeSlots::default(); + let mut slots: RawNodeSlots<3usize> = RawNodeSlots::default(); let mut current_element = elements.next(); if let Some(element) = ¤t_element { if element.kind() == T![infer] { @@ -7613,6 +7613,13 @@ impl SyntaxFactory for JsSyntaxFactory { } } slots.next_slot(); + if let Some(element) = ¤t_element { + if TsTypeConstraintClause::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); if current_element.is_some() { return RawSyntaxNode::new( TS_INFER_TYPE.to_bogus(), diff --git a/crates/rome_js_formatter/src/generated.rs b/crates/rome_js_formatter/src/generated.rs index 7afa4e79d3d..7e198b83ccd 100644 --- a/crates/rome_js_formatter/src/generated.rs +++ b/crates/rome_js_formatter/src/generated.rs @@ -8103,6 +8103,44 @@ impl IntoFormat for rome_js_syntax::TsTypeParameterName { ) } } +impl FormatRule + for crate::ts::auxiliary::type_constraint_clause::FormatTsTypeConstraintClause +{ + type Context = JsFormatContext; + #[inline(always)] + fn fmt( + &self, + node: &rome_js_syntax::TsTypeConstraintClause, + f: &mut JsFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) + } +} +impl AsFormat for rome_js_syntax::TsTypeConstraintClause { + type Format<'a> = FormatRefWithRule< + 'a, + rome_js_syntax::TsTypeConstraintClause, + crate::ts::auxiliary::type_constraint_clause::FormatTsTypeConstraintClause, + >; + fn format(&self) -> Self::Format<'_> { + FormatRefWithRule::new( + self, + crate::ts::auxiliary::type_constraint_clause::FormatTsTypeConstraintClause::default(), + ) + } +} +impl IntoFormat for rome_js_syntax::TsTypeConstraintClause { + type Format = FormatOwnedWithRule< + rome_js_syntax::TsTypeConstraintClause, + crate::ts::auxiliary::type_constraint_clause::FormatTsTypeConstraintClause, + >; + fn into_format(self) -> Self::Format { + FormatOwnedWithRule::new( + self, + crate::ts::auxiliary::type_constraint_clause::FormatTsTypeConstraintClause::default(), + ) + } +} impl FormatRule for crate::ts::types::predicate_return_type::FormatTsPredicateReturnType { @@ -8251,44 +8289,6 @@ impl IntoFormat for rome_js_syntax::TsTypeParameter { ) } } -impl FormatRule - for crate::ts::auxiliary::type_constraint_clause::FormatTsTypeConstraintClause -{ - type Context = JsFormatContext; - #[inline(always)] - fn fmt( - &self, - node: &rome_js_syntax::TsTypeConstraintClause, - f: &mut JsFormatter, - ) -> FormatResult<()> { - FormatNodeRule::::fmt(self, node, f) - } -} -impl AsFormat for rome_js_syntax::TsTypeConstraintClause { - type Format<'a> = FormatRefWithRule< - 'a, - rome_js_syntax::TsTypeConstraintClause, - crate::ts::auxiliary::type_constraint_clause::FormatTsTypeConstraintClause, - >; - fn format(&self) -> Self::Format<'_> { - FormatRefWithRule::new( - self, - crate::ts::auxiliary::type_constraint_clause::FormatTsTypeConstraintClause::default(), - ) - } -} -impl IntoFormat for rome_js_syntax::TsTypeConstraintClause { - type Format = FormatOwnedWithRule< - rome_js_syntax::TsTypeConstraintClause, - crate::ts::auxiliary::type_constraint_clause::FormatTsTypeConstraintClause, - >; - fn into_format(self) -> Self::Format { - FormatOwnedWithRule::new( - self, - crate::ts::auxiliary::type_constraint_clause::FormatTsTypeConstraintClause::default(), - ) - } -} impl FormatRule for crate::ts::auxiliary::default_type_clause::FormatTsDefaultTypeClause { diff --git a/crates/rome_js_formatter/src/parentheses.rs b/crates/rome_js_formatter/src/parentheses.rs index ef06b5472f1..2515b4bac35 100644 --- a/crates/rome_js_formatter/src/parentheses.rs +++ b/crates/rome_js_formatter/src/parentheses.rs @@ -41,12 +41,13 @@ use crate::utils::{AnyJsBinaryLikeExpression, AnyJsBinaryLikeLeftExpression}; use rome_js_syntax::{ AnyJsAssignment, AnyJsAssignmentPattern, AnyJsExpression, AnyJsFunctionBody, - AnyJsLiteralExpression, AnyTsType, JsArrowFunctionExpression, JsAssignmentExpression, - JsBinaryExpression, JsBinaryOperator, JsComputedMemberAssignment, JsComputedMemberExpression, - JsConditionalExpression, JsLanguage, JsParenthesizedAssignment, JsParenthesizedExpression, - JsPrivateName, JsSequenceExpression, JsStaticMemberAssignment, JsStaticMemberExpression, - JsSyntaxKind, JsSyntaxNode, JsSyntaxToken, TsConditionalType, TsIndexedAccessType, - TsIntersectionTypeElementList, TsParenthesizedType, TsUnionTypeVariantList, + AnyJsLiteralExpression, AnyTsReturnType, AnyTsType, JsArrowFunctionExpression, + JsAssignmentExpression, JsBinaryExpression, JsBinaryOperator, JsComputedMemberAssignment, + JsComputedMemberExpression, JsConditionalExpression, JsLanguage, JsParenthesizedAssignment, + JsParenthesizedExpression, JsPrivateName, JsSequenceExpression, JsStaticMemberAssignment, + JsStaticMemberExpression, JsSyntaxKind, JsSyntaxNode, JsSyntaxToken, TsConditionalType, + TsConstructorType, TsFunctionType, TsIndexedAccessType, TsIntersectionTypeElementList, + TsParenthesizedType, TsUnionTypeVariantList, }; use rome_rowan::{declare_node_union, match_ast, AstNode, AstSeparatedList, SyntaxResult}; @@ -725,6 +726,65 @@ pub(crate) fn is_check_type(node: &JsSyntaxNode, parent: &JsSyntaxNode) -> bool } } +/// Tests if `node` is the extends type of a [TsConditionalType] +/// +/// ```javascript +/// type s = A extends string ? boolean : number // true for `string`, false for `A`, `boolean` and `number` +/// ``` +fn is_extends_type(node: &JsSyntaxNode, parent: &JsSyntaxNode) -> bool { + debug_assert_is_parent(node, parent); + + match parent.kind() { + JsSyntaxKind::TS_CONDITIONAL_TYPE => { + let conditional = TsConditionalType::unwrap_cast(parent.clone()); + + conditional + .extends_type() + .map(AstNode::into_syntax) + .as_ref() + == Ok(node) + } + _ => false, + } +} + +/// Tests if `node` includes inferred return types with extends constraints +/// +/// ```javascript +/// type Type = A extends ((a: string) => infer B extends string) ? B : never; // true +/// ``` +pub(crate) fn is_includes_inferred_return_types_with_extends_constraints( + node: &JsSyntaxNode, + parent: &JsSyntaxNode, +) -> bool { + if is_extends_type(node, parent) { + let return_type = match node.kind() { + JsSyntaxKind::TS_FUNCTION_TYPE => { + match TsFunctionType::unwrap_cast(node.clone()).return_type() { + Ok(AnyTsReturnType::AnyTsType(any)) => Ok(any), + _ => { + return false; + } + } + } + JsSyntaxKind::TS_CONSTRUCTOR_TYPE => { + TsConstructorType::unwrap_cast(node.clone()).return_type() + } + + _ => { + return false; + } + }; + + match return_type { + Ok(AnyTsType::TsInferType(infer_type)) => infer_type.constraint().is_some(), + _ => false, + } + } else { + false + } +} + /// Returns `true` if node is in a union or intersection type with more than one variant /// /// ```javascript diff --git a/crates/rome_js_formatter/src/ts/types/function_type.rs b/crates/rome_js_formatter/src/ts/types/function_type.rs index d392640eee2..74d5e9db557 100644 --- a/crates/rome_js_formatter/src/ts/types/function_type.rs +++ b/crates/rome_js_formatter/src/ts/types/function_type.rs @@ -3,6 +3,7 @@ use crate::prelude::*; use crate::js::declarations::function_declaration::should_group_function_parameters; use crate::parentheses::{ is_check_type, is_in_many_type_union_or_intersection_list, + is_includes_inferred_return_types_with_extends_constraints, operator_type_or_higher_needs_parens, NeedsParentheses, }; use rome_formatter::write; @@ -78,6 +79,7 @@ pub(super) fn function_like_type_needs_parentheses( } _ => { is_check_type(node, parent) + || is_includes_inferred_return_types_with_extends_constraints(node, parent) || operator_type_or_higher_needs_parens(node, parent) || is_in_many_type_union_or_intersection_list(node, parent) } diff --git a/crates/rome_js_formatter/src/ts/types/infer_type.rs b/crates/rome_js_formatter/src/ts/types/infer_type.rs index fd262f94b71..60a48ffd49c 100644 --- a/crates/rome_js_formatter/src/ts/types/infer_type.rs +++ b/crates/rome_js_formatter/src/ts/types/infer_type.rs @@ -11,9 +11,17 @@ impl FormatNodeRule for FormatTsInferType { fn fmt_fields(&self, node: &TsInferType, f: &mut JsFormatter) -> FormatResult<()> { let TsInferTypeFields { infer_token, - type_parameter, + name, + constraint, } = node.as_fields(); - write![f, [infer_token.format(), space(), type_parameter.format()]] + + write!(f, [infer_token.format(), space(), name.format()])?; + + if let Some(constraint) = constraint { + write!(f, [space(), constraint.format()])?; + } + + Ok(()) } fn needs_parentheses(&self, item: &TsInferType) -> bool { diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/infer-extends/basic.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/infer-extends/basic.ts.snap deleted file mode 100644 index 62ba5d6ebd2..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/infer-extends/basic.ts.snap +++ /dev/null @@ -1,218 +0,0 @@ ---- -source: crates/rome_formatter_test/src/snapshot_builder.rs -info: - test_file: typescript/infer-extends/basic.ts ---- - -# Input - -```ts -type X3 = T extends [infer U extends number] ? MustBeNumber : never; -type X4 = T extends [infer U extends number, infer U extends number] ? MustBeNumber : never; -type X5 = T extends [infer U extends number, infer U] ? MustBeNumber : never; -type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; -type X7 = T extends [infer U extends string, infer U extends number] ? U : never; -type X8 = T extends infer U extends number ? U : T; -type X9 = T extends (infer U extends number ? U : T) ? U : T; - -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,15 +1,8 @@ - type X3 = T extends [infer U extends number] ? MustBeNumber : never; --type X4 = T extends [infer U extends number, infer U extends number] -- ? MustBeNumber -- : never; --type X5 = T extends [infer U extends number, infer U] -- ? MustBeNumber -- : never; --type X6 = T extends [infer U, infer U extends number] -- ? MustBeNumber -- : never; --type X7 = T extends [infer U extends string, infer U extends number] -- ? U -- : never; --type X8 = T extends infer U extends number ? U : T; -+type X4 = T extends [infer U extends number, infer U extends number] ? MustBeNumber : never; -+type X5 = T extends [infer U extends number, infer U] ? MustBeNumber : never; -+type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; -+type X7 = T extends [infer U extends string, infer U extends number] ? U : never; -+type X8 = T extends infer U extends number -+? U : T - type X9 = T extends (infer U extends number ? U : T) ? U : T; -``` - -# Output - -```ts -type X3 = T extends [infer U extends number] ? MustBeNumber : never; -type X4 = T extends [infer U extends number, infer U extends number] ? MustBeNumber : never; -type X5 = T extends [infer U extends number, infer U] ? MustBeNumber : never; -type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; -type X7 = T extends [infer U extends string, infer U extends number] ? U : never; -type X8 = T extends infer U extends number -? U : T -type X9 = T extends (infer U extends number ? U : T) ? U : T; -``` - -# Errors -``` -basic.ts:1:47 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `?` but instead found `]` - - > 1 │ type X3 = T extends [infer U extends number] ? MustBeNumber : never; - │ ^ - 2 │ type X4 = T extends [infer U extends number, infer U extends number] ? MustBeNumber : never; - 3 │ type X5 = T extends [infer U extends number, infer U] ? MustBeNumber : never; - - i Remove ] - -basic.ts:2:47 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `?` but instead found `,` - - 1 │ type X3 = T extends [infer U extends number] ? MustBeNumber : never; - > 2 │ type X4 = T extends [infer U extends number, infer U extends number] ? MustBeNumber : never; - │ ^ - 3 │ type X5 = T extends [infer U extends number, infer U] ? MustBeNumber : never; - 4 │ type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - - i Remove , - -basic.ts:2:71 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `?` but instead found `]` - - 1 │ type X3 = T extends [infer U extends number] ? MustBeNumber : never; - > 2 │ type X4 = T extends [infer U extends number, infer U extends number] ? MustBeNumber : never; - │ ^ - 3 │ type X5 = T extends [infer U extends number, infer U] ? MustBeNumber : never; - 4 │ type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - - i Remove ] - -basic.ts:3:47 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `?` but instead found `,` - - 1 │ type X3 = T extends [infer U extends number] ? MustBeNumber : never; - 2 │ type X4 = T extends [infer U extends number, infer U extends number] ? MustBeNumber : never; - > 3 │ type X5 = T extends [infer U extends number, infer U] ? MustBeNumber : never; - │ ^ - 4 │ type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - 5 │ type X7 = T extends [infer U extends string, infer U extends number] ? U : never; - - i Remove , - -basic.ts:4:56 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `?` but instead found `]` - - 2 │ type X4 = T extends [infer U extends number, infer U extends number] ? MustBeNumber : never; - 3 │ type X5 = T extends [infer U extends number, infer U] ? MustBeNumber : never; - > 4 │ type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - │ ^ - 5 │ type X7 = T extends [infer U extends string, infer U extends number] ? U : never; - 6 │ type X8 = T extends infer U extends number ? U : T; - - i Remove ] - -basic.ts:5:47 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `?` but instead found `,` - - 3 │ type X5 = T extends [infer U extends number, infer U] ? MustBeNumber : never; - 4 │ type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - > 5 │ type X7 = T extends [infer U extends string, infer U extends number] ? U : never; - │ ^ - 6 │ type X8 = T extends infer U extends number ? U : T; - 7 │ type X9 = T extends (infer U extends number ? U : T) ? U : T; - - i Remove , - -basic.ts:5:71 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `?` but instead found `]` - - 3 │ type X5 = T extends [infer U extends number, infer U] ? MustBeNumber : never; - 4 │ type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - > 5 │ type X7 = T extends [infer U extends string, infer U extends number] ? U : never; - │ ^ - 6 │ type X8 = T extends infer U extends number ? U : T; - 7 │ type X9 = T extends (infer U extends number ? U : T) ? U : T; - - i Remove ] - -basic.ts:6:35 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `?` but instead found `extends` - - 4 │ type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - 5 │ type X7 = T extends [infer U extends string, infer U extends number] ? U : never; - > 6 │ type X8 = T extends infer U extends number ? U : T; - │ ^^^^^^^ - 7 │ type X9 = T extends (infer U extends number ? U : T) ? U : T; - 8 │ - - i Remove extends - -basic.ts:6:43 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × expected `:` but instead found `number` - - 4 │ type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - 5 │ type X7 = T extends [infer U extends string, infer U extends number] ? U : never; - > 6 │ type X8 = T extends infer U extends number ? U : T; - │ ^^^^^^ - 7 │ type X9 = T extends (infer U extends number ? U : T) ? U : T; - 8 │ - - i Remove number - -basic.ts:6:50 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Expected a semicolon or an implicit semicolon after a statement, but found none - - 4 │ type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - 5 │ type X7 = T extends [infer U extends string, infer U extends number] ? U : never; - > 6 │ type X8 = T extends infer U extends number ? U : T; - │ ^ - 7 │ type X9 = T extends (infer U extends number ? U : T) ? U : T; - 8 │ - - i An explicit or implicit semicolon is expected here... - - 4 │ type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - 5 │ type X7 = T extends [infer U extends string, infer U extends number] ? U : never; - > 6 │ type X8 = T extends infer U extends number ? U : T; - │ ^ - 7 │ type X9 = T extends (infer U extends number ? U : T) ? U : T; - 8 │ - - i ...Which is required to end this statement - - 4 │ type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - 5 │ type X7 = T extends [infer U extends string, infer U extends number] ? U : never; - > 6 │ type X8 = T extends infer U extends number ? U : T; - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 7 │ type X9 = T extends (infer U extends number ? U : T) ? U : T; - 8 │ - - -``` - -# Lines exceeding max width of 80 characters -``` - 2: type X4 = T extends [infer U extends number, infer U extends number] ? MustBeNumber : never; - 3: type X5 = T extends [infer U extends number, infer U] ? MustBeNumber : never; - 4: type X6 = T extends [infer U, infer U extends number] ? MustBeNumber : never; - 5: type X7 = T extends [infer U extends string, infer U extends number] ? U : never; -``` - - diff --git a/crates/rome_js_parser/src/state.rs b/crates/rome_js_parser/src/state.rs index 26ec5986648..07839dca0f8 100644 --- a/crates/rome_js_parser/src/state.rs +++ b/crates/rome_js_parser/src/state.rs @@ -164,6 +164,12 @@ impl ParserState { .contains(ParsingContextFlags::BREAK_ALLOWED) } + pub fn allow_conditional_type(&self) -> bool { + !self + .parsing_context + .contains(ParsingContextFlags::DISALLOW_CONDITIONAL_TYPE) + } + pub fn strict(&self) -> Option<&StrictMode> { self.strict.as_ref() } @@ -371,7 +377,7 @@ bitflags! { /// snapshots each individual boolean field to allow restoring the previous state. With bitflags, all that /// is needed is to copy away the flags field and restore it after. #[derive(Default)] - pub(crate) struct ParsingContextFlags: u8 { + pub(crate) struct ParsingContextFlags: u16 { /// Whether the parser is in a generator function like `function* a() {}` /// Matches the `Yield` parameter in the ECMA spec const IN_GENERATOR = 1 << 0; @@ -397,6 +403,8 @@ bitflags! { /// Whatever the parser is in a TypeScript ambient context const AMBIENT_CONTEXT = 1 << 7; + const DISALLOW_CONDITIONAL_TYPE = 1 << 8; + const LOOP = Self::BREAK_ALLOWED.bits | Self::CONTINUE_ALLOWED.bits; /// Bitmask of all the flags that must be reset (shouldn't be inherited) when the parser enters a function @@ -580,6 +588,27 @@ impl ChangeParserStateFlags for EnterType { } } +pub(crate) struct EnterConditionalTypes(bool); + +impl EnterConditionalTypes { + pub(crate) const fn allow() -> Self { + Self(true) + } + pub(crate) const fn disallow() -> Self { + Self(false) + } +} + +impl ChangeParserStateFlags for EnterConditionalTypes { + fn compute_new_flags(&self, existing: ParsingContextFlags) -> ParsingContextFlags { + if self.0 { + existing - ParsingContextFlags::DISALLOW_CONDITIONAL_TYPE + } else { + existing | ParsingContextFlags::DISALLOW_CONDITIONAL_TYPE + } + } +} + #[derive(Default)] pub(crate) struct EnterAmbientContextSnapshot { flags: ParsingContextFlags, diff --git a/crates/rome_js_parser/src/syntax/typescript/types.rs b/crates/rome_js_parser/src/syntax/typescript/types.rs index ead88502d18..b7b88d989c7 100644 --- a/crates/rome_js_parser/src/syntax/typescript/types.rs +++ b/crates/rome_js_parser/src/syntax/typescript/types.rs @@ -1,6 +1,6 @@ use crate::parser::{RecoveryError, RecoveryResult}; use crate::prelude::*; -use crate::state::{EnterType, SignatureFlags}; +use crate::state::{EnterConditionalTypes, EnterType, SignatureFlags}; use crate::syntax::expr::{ is_at_binary_operator, is_at_expression, is_at_identifier, is_nth_at_identifier, is_nth_at_identifier_or_keyword, parse_big_int_literal_expression, parse_identifier, @@ -20,6 +20,7 @@ use crate::syntax::object::{ use crate::syntax::stmt::optional_semi; use crate::syntax::typescript::try_parse; use crate::syntax::typescript::ts_parse_error::{expected_ts_type, expected_ts_type_parameter}; + use rome_parser::parse_lists::{ParseNodeList, ParseSeparatedList}; use crate::lexer::{LexContext, ReLexContext}; @@ -196,21 +197,6 @@ fn is_nth_at_ts_type_parameters(p: &mut JsParser, n: usize) -> bool { #[inline(always)] pub(crate) fn parse_ts_type(p: &mut JsParser) -> ParsedSyntax { - parse_ts_type_impl(p, ConditionalType::Allowed) -} - -enum ConditionalType { - Allowed, - Disallowed, -} - -impl ConditionalType { - fn is_allowed(&self) -> bool { - matches!(self, ConditionalType::Allowed) - } -} - -fn parse_ts_type_impl(p: &mut JsParser, conditional_type: ConditionalType) -> ParsedSyntax { p.with_state(EnterType, |p| { if is_at_constructor_type(p) { return parse_ts_constructor_type(p); @@ -224,16 +210,23 @@ fn parse_ts_type_impl(p: &mut JsParser, conditional_type: ConditionalType) -> Pa // test ts ts_conditional_type_call_signature_lhs // type X = V extends (...args: any[]) => any ? (...args: Parameters) => void : Function; - if conditional_type.is_allowed() { + if p.state().allow_conditional_type() { left.map(|left| { // test ts ts_conditional_type // type A = number; // type B = string extends number ? string : number; // type C = A extends (B extends A ? number : string) ? void : number; + // type D = T extends [infer S extends string, ...unknown[]] ? S : never; + // type E = T extends (infer U extends number ? U : T ) ? U : T + // type F = T extends { [P in infer U extends keyof T ? 1 : 0]: 1; } ? 1 : 0; + // type G = T extends [unknown, infer S extends string] ? S : never; + // type H = A extends () => B extends C ? D : E ? F : G; + // type J = T extends ((...a: any[]) => infer R extends string) ? R : never; if !p.has_preceding_line_break() && p.at(T![extends]) { let m = left.precede(p); p.expect(T![extends]); - parse_ts_type_impl(p, ConditionalType::Disallowed) + + p.with_state(EnterConditionalTypes::disallow(), parse_ts_type) .or_add_diagnostic(p, expected_ts_type); p.expect(T![?]); parse_ts_type(p).or_add_diagnostic(p, expected_ts_type); @@ -361,6 +354,7 @@ fn parse_ts_primary_type(p: &mut JsParser) -> ParsedSyntax { let m = p.start(); p.expect(T![infer]); parse_ts_type_parameter_name(p).or_add_diagnostic(p, expected_identifier); + try_parse_constraint_of_infer_type(p).ok(); return Present(m.complete(p, TS_INFER_TYPE)); } @@ -377,7 +371,31 @@ fn parse_ts_primary_type(p: &mut JsParser) -> ParsedSyntax { return Present(m.complete(p, TS_TYPE_OPERATOR_TYPE)); } - parse_postfix_type_or_higher(p) + p.with_state(EnterConditionalTypes::allow(), parse_postfix_type_or_higher) +} + +fn try_parse_constraint_of_infer_type(p: &mut JsParser) -> ParsedSyntax { + if !p.at(T![extends]) { + return Absent; + } + + try_parse(p, |p| { + let parsed = p + .with_state( + EnterConditionalTypes::disallow(), + parse_ts_type_constraint_clause, + ) + .expect("Type constraint clause because parser is positioned at expect clause"); + + // Rewind if conditional types are allowed, and the parser is at the `?` token because + // this should instead be parsed as a conditional type. + if p.state.allow_conditional_type() && p.at(T![?]) { + Err(()) + } else { + Ok(Present(parsed)) + } + }) + .unwrap_or(Absent) } fn parse_postfix_type_or_higher(p: &mut JsParser) -> ParsedSyntax { @@ -566,7 +584,8 @@ fn parse_ts_parenthesized_type(p: &mut JsParser) -> ParsedSyntax { let m = p.start(); p.bump(T!['(']); - parse_ts_type(p).or_add_diagnostic(p, expected_ts_type); + p.with_state(EnterConditionalTypes::allow(), parse_ts_type) + .or_add_diagnostic(p, expected_ts_type); p.expect(T![')']); Present(m.complete(p, TS_PARENTHESIZED_TYPE)) } @@ -1201,11 +1220,13 @@ fn parse_ts_return_type(p: &mut JsParser) -> ParsedSyntax { p.at(T![asserts]) && (is_nth_at_identifier(p, 1) || p.nth_at(1, T![this])); let is_is_predicate = (is_at_identifier(p) || p.at(T![this])) && p.nth_at(1, T![is]); - if !p.has_nth_preceding_line_break(1) && (is_asserts_predicate || is_is_predicate) { - parse_ts_type_predicate(p) - } else { - parse_ts_type(p) - } + p.with_state(EnterConditionalTypes::allow(), |p| { + if !p.has_nth_preceding_line_break(1) && (is_asserts_predicate || is_is_predicate) { + parse_ts_type_predicate(p) + } else { + parse_ts_type(p) + } + }) } // test ts ts_type_predicate diff --git a/crates/rome_js_parser/test_data/inline/ok/ts_conditional_type.rast b/crates/rome_js_parser/test_data/inline/ok/ts_conditional_type.rast index ef4de51cc0f..6da4e41e738 100644 --- a/crates/rome_js_parser/test_data/inline/ok/ts_conditional_type.rast +++ b/crates/rome_js_parser/test_data/inline/ok/ts_conditional_type.rast @@ -93,14 +93,473 @@ JsModule { }, semicolon_token: SEMICOLON@133..134 ";" [] [], }, + TsTypeAliasDeclaration { + type_token: TYPE_KW@134..140 "type" [Newline("\n")] [Whitespace(" ")], + binding_identifier: TsIdentifierBinding { + name_token: IDENT@140..141 "D" [] [], + }, + type_parameters: TsTypeParameters { + l_angle_token: L_ANGLE@141..142 "<" [] [], + items: TsTypeParameterList [ + TsTypeParameter { + name: TsTypeParameterName { + ident_token: IDENT@142..143 "T" [] [], + }, + constraint: missing (optional), + default: missing (optional), + }, + ], + r_angle_token: R_ANGLE@143..145 ">" [] [Whitespace(" ")], + }, + eq_token: EQ@145..147 "=" [] [Whitespace(" ")], + ty: TsConditionalType { + check_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@147..149 "T" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + extends_token: EXTENDS_KW@149..157 "extends" [] [Whitespace(" ")], + extends_type: TsTupleType { + l_brack_token: L_BRACK@157..158 "[" [] [], + elements: TsTupleTypeElementList [ + TsInferType { + infer_token: INFER_KW@158..164 "infer" [] [Whitespace(" ")], + name: TsTypeParameterName { + ident_token: IDENT@164..166 "S" [] [Whitespace(" ")], + }, + constraint: TsTypeConstraintClause { + extends_token: EXTENDS_KW@166..174 "extends" [] [Whitespace(" ")], + ty: TsStringType { + string_token: STRING_KW@174..180 "string" [] [], + }, + }, + }, + COMMA@180..182 "," [] [Whitespace(" ")], + TsRestTupleTypeElement { + dotdotdot_token: DOT3@182..185 "..." [] [], + ty: TsArrayType { + element_type: TsUnknownType { + unknown_token: UNKNOWN_KW@185..192 "unknown" [] [], + }, + l_brack_token: L_BRACK@192..193 "[" [] [], + r_brack_token: R_BRACK@193..194 "]" [] [], + }, + }, + ], + r_brack_token: R_BRACK@194..196 "]" [] [Whitespace(" ")], + }, + question_mark_token: QUESTION@196..198 "?" [] [Whitespace(" ")], + true_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@198..200 "S" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + colon_token: COLON@200..202 ":" [] [Whitespace(" ")], + false_type: TsNeverType { + never_token: NEVER_KW@202..207 "never" [] [], + }, + }, + semicolon_token: SEMICOLON@207..208 ";" [] [], + }, + TsTypeAliasDeclaration { + type_token: TYPE_KW@208..214 "type" [Newline("\n")] [Whitespace(" ")], + binding_identifier: TsIdentifierBinding { + name_token: IDENT@214..215 "E" [] [], + }, + type_parameters: TsTypeParameters { + l_angle_token: L_ANGLE@215..216 "<" [] [], + items: TsTypeParameterList [ + TsTypeParameter { + name: TsTypeParameterName { + ident_token: IDENT@216..217 "U" [] [], + }, + constraint: missing (optional), + default: missing (optional), + }, + COMMA@217..219 "," [] [Whitespace(" ")], + TsTypeParameter { + name: TsTypeParameterName { + ident_token: IDENT@219..220 "T" [] [], + }, + constraint: missing (optional), + default: missing (optional), + }, + ], + r_angle_token: R_ANGLE@220..222 ">" [] [Whitespace(" ")], + }, + eq_token: EQ@222..224 "=" [] [Whitespace(" ")], + ty: TsConditionalType { + check_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@224..226 "T" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + extends_token: EXTENDS_KW@226..234 "extends" [] [Whitespace(" ")], + extends_type: TsParenthesizedType { + l_paren_token: L_PAREN@234..235 "(" [] [], + ty: TsConditionalType { + check_type: TsInferType { + infer_token: INFER_KW@235..241 "infer" [] [Whitespace(" ")], + name: TsTypeParameterName { + ident_token: IDENT@241..243 "U" [] [Whitespace(" ")], + }, + constraint: missing (optional), + }, + extends_token: EXTENDS_KW@243..251 "extends" [] [Whitespace(" ")], + extends_type: TsNumberType { + number_token: NUMBER_KW@251..258 "number" [] [Whitespace(" ")], + }, + question_mark_token: QUESTION@258..260 "?" [] [Whitespace(" ")], + true_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@260..262 "U" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + colon_token: COLON@262..264 ":" [] [Whitespace(" ")], + false_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@264..266 "T" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + }, + r_paren_token: R_PAREN@266..268 ")" [] [Whitespace(" ")], + }, + question_mark_token: QUESTION@268..270 "?" [] [Whitespace(" ")], + true_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@270..272 "U" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + colon_token: COLON@272..274 ":" [] [Whitespace(" ")], + false_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@274..275 "T" [] [], + }, + type_arguments: missing (optional), + }, + }, + semicolon_token: missing (optional), + }, + TsTypeAliasDeclaration { + type_token: TYPE_KW@275..281 "type" [Newline("\n")] [Whitespace(" ")], + binding_identifier: TsIdentifierBinding { + name_token: IDENT@281..282 "F" [] [], + }, + type_parameters: TsTypeParameters { + l_angle_token: L_ANGLE@282..283 "<" [] [], + items: TsTypeParameterList [ + TsTypeParameter { + name: TsTypeParameterName { + ident_token: IDENT@283..284 "T" [] [], + }, + constraint: missing (optional), + default: missing (optional), + }, + ], + r_angle_token: R_ANGLE@284..286 ">" [] [Whitespace(" ")], + }, + eq_token: EQ@286..288 "=" [] [Whitespace(" ")], + ty: TsConditionalType { + check_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@288..290 "T" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + extends_token: EXTENDS_KW@290..298 "extends" [] [Whitespace(" ")], + extends_type: TsMappedType { + l_curly_token: L_CURLY@298..300 "{" [] [Whitespace(" ")], + readonly_modifier: missing (optional), + l_brack_token: L_BRACK@300..301 "[" [] [], + property_name: TsTypeParameterName { + ident_token: IDENT@301..303 "P" [] [Whitespace(" ")], + }, + in_token: IN_KW@303..306 "in" [] [Whitespace(" ")], + keys_type: TsConditionalType { + check_type: TsInferType { + infer_token: INFER_KW@306..312 "infer" [] [Whitespace(" ")], + name: TsTypeParameterName { + ident_token: IDENT@312..314 "U" [] [Whitespace(" ")], + }, + constraint: missing (optional), + }, + extends_token: EXTENDS_KW@314..322 "extends" [] [Whitespace(" ")], + extends_type: TsTypeOperatorType { + operator_token: KEYOF_KW@322..328 "keyof" [] [Whitespace(" ")], + ty: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@328..330 "T" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + }, + question_mark_token: QUESTION@330..332 "?" [] [Whitespace(" ")], + true_type: TsNumberLiteralType { + minus_token: missing (optional), + literal_token: JS_NUMBER_LITERAL@332..334 "1" [] [Whitespace(" ")], + }, + colon_token: COLON@334..336 ":" [] [Whitespace(" ")], + false_type: TsNumberLiteralType { + minus_token: missing (optional), + literal_token: JS_NUMBER_LITERAL@336..337 "0" [] [], + }, + }, + as_clause: missing (optional), + r_brack_token: R_BRACK@337..338 "]" [] [], + optional_modifier: missing (optional), + mapped_type: TsTypeAnnotation { + colon_token: COLON@338..340 ":" [] [Whitespace(" ")], + ty: TsNumberLiteralType { + minus_token: missing (optional), + literal_token: JS_NUMBER_LITERAL@340..341 "1" [] [], + }, + }, + semicolon_token: SEMICOLON@341..343 ";" [] [Whitespace(" ")], + r_curly_token: R_CURLY@343..345 "}" [] [Whitespace(" ")], + }, + question_mark_token: QUESTION@345..347 "?" [] [Whitespace(" ")], + true_type: TsNumberLiteralType { + minus_token: missing (optional), + literal_token: JS_NUMBER_LITERAL@347..349 "1" [] [Whitespace(" ")], + }, + colon_token: COLON@349..351 ":" [] [Whitespace(" ")], + false_type: TsNumberLiteralType { + minus_token: missing (optional), + literal_token: JS_NUMBER_LITERAL@351..352 "0" [] [], + }, + }, + semicolon_token: SEMICOLON@352..353 ";" [] [], + }, + TsTypeAliasDeclaration { + type_token: TYPE_KW@353..359 "type" [Newline("\n")] [Whitespace(" ")], + binding_identifier: TsIdentifierBinding { + name_token: IDENT@359..360 "G" [] [], + }, + type_parameters: TsTypeParameters { + l_angle_token: L_ANGLE@360..361 "<" [] [], + items: TsTypeParameterList [ + TsTypeParameter { + name: TsTypeParameterName { + ident_token: IDENT@361..362 "T" [] [], + }, + constraint: missing (optional), + default: missing (optional), + }, + ], + r_angle_token: R_ANGLE@362..364 ">" [] [Whitespace(" ")], + }, + eq_token: EQ@364..366 "=" [] [Whitespace(" ")], + ty: TsConditionalType { + check_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@366..368 "T" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + extends_token: EXTENDS_KW@368..376 "extends" [] [Whitespace(" ")], + extends_type: TsTupleType { + l_brack_token: L_BRACK@376..377 "[" [] [], + elements: TsTupleTypeElementList [ + TsUnknownType { + unknown_token: UNKNOWN_KW@377..384 "unknown" [] [], + }, + COMMA@384..386 "," [] [Whitespace(" ")], + TsInferType { + infer_token: INFER_KW@386..392 "infer" [] [Whitespace(" ")], + name: TsTypeParameterName { + ident_token: IDENT@392..394 "S" [] [Whitespace(" ")], + }, + constraint: TsTypeConstraintClause { + extends_token: EXTENDS_KW@394..402 "extends" [] [Whitespace(" ")], + ty: TsStringType { + string_token: STRING_KW@402..408 "string" [] [], + }, + }, + }, + ], + r_brack_token: R_BRACK@408..410 "]" [] [Whitespace(" ")], + }, + question_mark_token: QUESTION@410..412 "?" [] [Whitespace(" ")], + true_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@412..414 "S" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + colon_token: COLON@414..416 ":" [] [Whitespace(" ")], + false_type: TsNeverType { + never_token: NEVER_KW@416..421 "never" [] [], + }, + }, + semicolon_token: SEMICOLON@421..422 ";" [] [], + }, + TsTypeAliasDeclaration { + type_token: TYPE_KW@422..428 "type" [Newline("\n")] [Whitespace(" ")], + binding_identifier: TsIdentifierBinding { + name_token: IDENT@428..430 "H" [] [Whitespace(" ")], + }, + type_parameters: missing (optional), + eq_token: EQ@430..432 "=" [] [Whitespace(" ")], + ty: TsConditionalType { + check_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@432..434 "A" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + extends_token: EXTENDS_KW@434..442 "extends" [] [Whitespace(" ")], + extends_type: TsFunctionType { + type_parameters: missing (optional), + parameters: JsParameters { + l_paren_token: L_PAREN@442..443 "(" [] [], + items: JsParameterList [], + r_paren_token: R_PAREN@443..445 ")" [] [Whitespace(" ")], + }, + fat_arrow_token: FAT_ARROW@445..448 "=>" [] [Whitespace(" ")], + return_type: TsConditionalType { + check_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@448..450 "B" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + extends_token: EXTENDS_KW@450..458 "extends" [] [Whitespace(" ")], + extends_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@458..460 "C" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + question_mark_token: QUESTION@460..462 "?" [] [Whitespace(" ")], + true_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@462..464 "D" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + colon_token: COLON@464..466 ":" [] [Whitespace(" ")], + false_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@466..468 "E" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + }, + }, + question_mark_token: QUESTION@468..470 "?" [] [Whitespace(" ")], + true_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@470..472 "F" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + colon_token: COLON@472..474 ":" [] [Whitespace(" ")], + false_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@474..475 "G" [] [], + }, + type_arguments: missing (optional), + }, + }, + semicolon_token: SEMICOLON@475..476 ";" [] [], + }, + TsTypeAliasDeclaration { + type_token: TYPE_KW@476..482 "type" [Newline("\n")] [Whitespace(" ")], + binding_identifier: TsIdentifierBinding { + name_token: IDENT@482..483 "J" [] [], + }, + type_parameters: TsTypeParameters { + l_angle_token: L_ANGLE@483..484 "<" [] [], + items: TsTypeParameterList [ + TsTypeParameter { + name: TsTypeParameterName { + ident_token: IDENT@484..485 "T" [] [], + }, + constraint: missing (optional), + default: missing (optional), + }, + ], + r_angle_token: R_ANGLE@485..487 ">" [] [Whitespace(" ")], + }, + eq_token: EQ@487..489 "=" [] [Whitespace(" ")], + ty: TsConditionalType { + check_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@489..491 "T" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + extends_token: EXTENDS_KW@491..499 "extends" [] [Whitespace(" ")], + extends_type: TsParenthesizedType { + l_paren_token: L_PAREN@499..500 "(" [] [], + ty: TsFunctionType { + type_parameters: missing (optional), + parameters: JsParameters { + l_paren_token: L_PAREN@500..501 "(" [] [], + items: JsParameterList [ + JsRestParameter { + dotdotdot_token: DOT3@501..504 "..." [] [], + binding: JsIdentifierBinding { + name_token: IDENT@504..505 "a" [] [], + }, + type_annotation: TsTypeAnnotation { + colon_token: COLON@505..507 ":" [] [Whitespace(" ")], + ty: TsArrayType { + element_type: TsAnyType { + any_token: ANY_KW@507..510 "any" [] [], + }, + l_brack_token: L_BRACK@510..511 "[" [] [], + r_brack_token: R_BRACK@511..512 "]" [] [], + }, + }, + }, + ], + r_paren_token: R_PAREN@512..514 ")" [] [Whitespace(" ")], + }, + fat_arrow_token: FAT_ARROW@514..517 "=>" [] [Whitespace(" ")], + return_type: TsInferType { + infer_token: INFER_KW@517..523 "infer" [] [Whitespace(" ")], + name: TsTypeParameterName { + ident_token: IDENT@523..525 "R" [] [Whitespace(" ")], + }, + constraint: TsTypeConstraintClause { + extends_token: EXTENDS_KW@525..533 "extends" [] [Whitespace(" ")], + ty: TsStringType { + string_token: STRING_KW@533..539 "string" [] [], + }, + }, + }, + }, + r_paren_token: R_PAREN@539..541 ")" [] [Whitespace(" ")], + }, + question_mark_token: QUESTION@541..543 "?" [] [Whitespace(" ")], + true_type: TsReferenceType { + name: JsReferenceIdentifier { + value_token: IDENT@543..545 "R" [] [Whitespace(" ")], + }, + type_arguments: missing (optional), + }, + colon_token: COLON@545..547 ":" [] [Whitespace(" ")], + false_type: TsNeverType { + never_token: NEVER_KW@547..552 "never" [] [], + }, + }, + semicolon_token: SEMICOLON@552..553 ";" [] [], + }, ], - eof_token: EOF@134..135 "" [Newline("\n")] [], + eof_token: EOF@553..554 "" [Newline("\n")] [], } -0: JS_MODULE@0..135 +0: JS_MODULE@0..554 0: (empty) 1: JS_DIRECTIVE_LIST@0..0 - 2: JS_MODULE_ITEM_LIST@0..134 + 2: JS_MODULE_ITEM_LIST@0..553 0: TS_TYPE_ALIAS_DECLARATION@0..16 0: TYPE_KW@0..5 "type" [] [Whitespace(" ")] 1: TS_IDENTIFIER_BINDING@5..7 @@ -167,4 +626,331 @@ JsModule { 6: TS_NUMBER_TYPE@127..133 0: NUMBER_KW@127..133 "number" [] [] 5: SEMICOLON@133..134 ";" [] [] - 3: EOF@134..135 "" [Newline("\n")] [] + 3: TS_TYPE_ALIAS_DECLARATION@134..208 + 0: TYPE_KW@134..140 "type" [Newline("\n")] [Whitespace(" ")] + 1: TS_IDENTIFIER_BINDING@140..141 + 0: IDENT@140..141 "D" [] [] + 2: TS_TYPE_PARAMETERS@141..145 + 0: L_ANGLE@141..142 "<" [] [] + 1: TS_TYPE_PARAMETER_LIST@142..143 + 0: TS_TYPE_PARAMETER@142..143 + 0: TS_TYPE_PARAMETER_NAME@142..143 + 0: IDENT@142..143 "T" [] [] + 1: (empty) + 2: (empty) + 2: R_ANGLE@143..145 ">" [] [Whitespace(" ")] + 3: EQ@145..147 "=" [] [Whitespace(" ")] + 4: TS_CONDITIONAL_TYPE@147..207 + 0: TS_REFERENCE_TYPE@147..149 + 0: JS_REFERENCE_IDENTIFIER@147..149 + 0: IDENT@147..149 "T" [] [Whitespace(" ")] + 1: (empty) + 1: EXTENDS_KW@149..157 "extends" [] [Whitespace(" ")] + 2: TS_TUPLE_TYPE@157..196 + 0: L_BRACK@157..158 "[" [] [] + 1: TS_TUPLE_TYPE_ELEMENT_LIST@158..194 + 0: TS_INFER_TYPE@158..180 + 0: INFER_KW@158..164 "infer" [] [Whitespace(" ")] + 1: TS_TYPE_PARAMETER_NAME@164..166 + 0: IDENT@164..166 "S" [] [Whitespace(" ")] + 2: TS_TYPE_CONSTRAINT_CLAUSE@166..180 + 0: EXTENDS_KW@166..174 "extends" [] [Whitespace(" ")] + 1: TS_STRING_TYPE@174..180 + 0: STRING_KW@174..180 "string" [] [] + 1: COMMA@180..182 "," [] [Whitespace(" ")] + 2: TS_REST_TUPLE_TYPE_ELEMENT@182..194 + 0: DOT3@182..185 "..." [] [] + 1: TS_ARRAY_TYPE@185..194 + 0: TS_UNKNOWN_TYPE@185..192 + 0: UNKNOWN_KW@185..192 "unknown" [] [] + 1: L_BRACK@192..193 "[" [] [] + 2: R_BRACK@193..194 "]" [] [] + 2: R_BRACK@194..196 "]" [] [Whitespace(" ")] + 3: QUESTION@196..198 "?" [] [Whitespace(" ")] + 4: TS_REFERENCE_TYPE@198..200 + 0: JS_REFERENCE_IDENTIFIER@198..200 + 0: IDENT@198..200 "S" [] [Whitespace(" ")] + 1: (empty) + 5: COLON@200..202 ":" [] [Whitespace(" ")] + 6: TS_NEVER_TYPE@202..207 + 0: NEVER_KW@202..207 "never" [] [] + 5: SEMICOLON@207..208 ";" [] [] + 4: TS_TYPE_ALIAS_DECLARATION@208..275 + 0: TYPE_KW@208..214 "type" [Newline("\n")] [Whitespace(" ")] + 1: TS_IDENTIFIER_BINDING@214..215 + 0: IDENT@214..215 "E" [] [] + 2: TS_TYPE_PARAMETERS@215..222 + 0: L_ANGLE@215..216 "<" [] [] + 1: TS_TYPE_PARAMETER_LIST@216..220 + 0: TS_TYPE_PARAMETER@216..217 + 0: TS_TYPE_PARAMETER_NAME@216..217 + 0: IDENT@216..217 "U" [] [] + 1: (empty) + 2: (empty) + 1: COMMA@217..219 "," [] [Whitespace(" ")] + 2: TS_TYPE_PARAMETER@219..220 + 0: TS_TYPE_PARAMETER_NAME@219..220 + 0: IDENT@219..220 "T" [] [] + 1: (empty) + 2: (empty) + 2: R_ANGLE@220..222 ">" [] [Whitespace(" ")] + 3: EQ@222..224 "=" [] [Whitespace(" ")] + 4: TS_CONDITIONAL_TYPE@224..275 + 0: TS_REFERENCE_TYPE@224..226 + 0: JS_REFERENCE_IDENTIFIER@224..226 + 0: IDENT@224..226 "T" [] [Whitespace(" ")] + 1: (empty) + 1: EXTENDS_KW@226..234 "extends" [] [Whitespace(" ")] + 2: TS_PARENTHESIZED_TYPE@234..268 + 0: L_PAREN@234..235 "(" [] [] + 1: TS_CONDITIONAL_TYPE@235..266 + 0: TS_INFER_TYPE@235..243 + 0: INFER_KW@235..241 "infer" [] [Whitespace(" ")] + 1: TS_TYPE_PARAMETER_NAME@241..243 + 0: IDENT@241..243 "U" [] [Whitespace(" ")] + 2: (empty) + 1: EXTENDS_KW@243..251 "extends" [] [Whitespace(" ")] + 2: TS_NUMBER_TYPE@251..258 + 0: NUMBER_KW@251..258 "number" [] [Whitespace(" ")] + 3: QUESTION@258..260 "?" [] [Whitespace(" ")] + 4: TS_REFERENCE_TYPE@260..262 + 0: JS_REFERENCE_IDENTIFIER@260..262 + 0: IDENT@260..262 "U" [] [Whitespace(" ")] + 1: (empty) + 5: COLON@262..264 ":" [] [Whitespace(" ")] + 6: TS_REFERENCE_TYPE@264..266 + 0: JS_REFERENCE_IDENTIFIER@264..266 + 0: IDENT@264..266 "T" [] [Whitespace(" ")] + 1: (empty) + 2: R_PAREN@266..268 ")" [] [Whitespace(" ")] + 3: QUESTION@268..270 "?" [] [Whitespace(" ")] + 4: TS_REFERENCE_TYPE@270..272 + 0: JS_REFERENCE_IDENTIFIER@270..272 + 0: IDENT@270..272 "U" [] [Whitespace(" ")] + 1: (empty) + 5: COLON@272..274 ":" [] [Whitespace(" ")] + 6: TS_REFERENCE_TYPE@274..275 + 0: JS_REFERENCE_IDENTIFIER@274..275 + 0: IDENT@274..275 "T" [] [] + 1: (empty) + 5: (empty) + 5: TS_TYPE_ALIAS_DECLARATION@275..353 + 0: TYPE_KW@275..281 "type" [Newline("\n")] [Whitespace(" ")] + 1: TS_IDENTIFIER_BINDING@281..282 + 0: IDENT@281..282 "F" [] [] + 2: TS_TYPE_PARAMETERS@282..286 + 0: L_ANGLE@282..283 "<" [] [] + 1: TS_TYPE_PARAMETER_LIST@283..284 + 0: TS_TYPE_PARAMETER@283..284 + 0: TS_TYPE_PARAMETER_NAME@283..284 + 0: IDENT@283..284 "T" [] [] + 1: (empty) + 2: (empty) + 2: R_ANGLE@284..286 ">" [] [Whitespace(" ")] + 3: EQ@286..288 "=" [] [Whitespace(" ")] + 4: TS_CONDITIONAL_TYPE@288..352 + 0: TS_REFERENCE_TYPE@288..290 + 0: JS_REFERENCE_IDENTIFIER@288..290 + 0: IDENT@288..290 "T" [] [Whitespace(" ")] + 1: (empty) + 1: EXTENDS_KW@290..298 "extends" [] [Whitespace(" ")] + 2: TS_MAPPED_TYPE@298..345 + 0: L_CURLY@298..300 "{" [] [Whitespace(" ")] + 1: (empty) + 2: L_BRACK@300..301 "[" [] [] + 3: TS_TYPE_PARAMETER_NAME@301..303 + 0: IDENT@301..303 "P" [] [Whitespace(" ")] + 4: IN_KW@303..306 "in" [] [Whitespace(" ")] + 5: TS_CONDITIONAL_TYPE@306..337 + 0: TS_INFER_TYPE@306..314 + 0: INFER_KW@306..312 "infer" [] [Whitespace(" ")] + 1: TS_TYPE_PARAMETER_NAME@312..314 + 0: IDENT@312..314 "U" [] [Whitespace(" ")] + 2: (empty) + 1: EXTENDS_KW@314..322 "extends" [] [Whitespace(" ")] + 2: TS_TYPE_OPERATOR_TYPE@322..330 + 0: KEYOF_KW@322..328 "keyof" [] [Whitespace(" ")] + 1: TS_REFERENCE_TYPE@328..330 + 0: JS_REFERENCE_IDENTIFIER@328..330 + 0: IDENT@328..330 "T" [] [Whitespace(" ")] + 1: (empty) + 3: QUESTION@330..332 "?" [] [Whitespace(" ")] + 4: TS_NUMBER_LITERAL_TYPE@332..334 + 0: (empty) + 1: JS_NUMBER_LITERAL@332..334 "1" [] [Whitespace(" ")] + 5: COLON@334..336 ":" [] [Whitespace(" ")] + 6: TS_NUMBER_LITERAL_TYPE@336..337 + 0: (empty) + 1: JS_NUMBER_LITERAL@336..337 "0" [] [] + 6: (empty) + 7: R_BRACK@337..338 "]" [] [] + 8: (empty) + 9: TS_TYPE_ANNOTATION@338..341 + 0: COLON@338..340 ":" [] [Whitespace(" ")] + 1: TS_NUMBER_LITERAL_TYPE@340..341 + 0: (empty) + 1: JS_NUMBER_LITERAL@340..341 "1" [] [] + 10: SEMICOLON@341..343 ";" [] [Whitespace(" ")] + 11: R_CURLY@343..345 "}" [] [Whitespace(" ")] + 3: QUESTION@345..347 "?" [] [Whitespace(" ")] + 4: TS_NUMBER_LITERAL_TYPE@347..349 + 0: (empty) + 1: JS_NUMBER_LITERAL@347..349 "1" [] [Whitespace(" ")] + 5: COLON@349..351 ":" [] [Whitespace(" ")] + 6: TS_NUMBER_LITERAL_TYPE@351..352 + 0: (empty) + 1: JS_NUMBER_LITERAL@351..352 "0" [] [] + 5: SEMICOLON@352..353 ";" [] [] + 6: TS_TYPE_ALIAS_DECLARATION@353..422 + 0: TYPE_KW@353..359 "type" [Newline("\n")] [Whitespace(" ")] + 1: TS_IDENTIFIER_BINDING@359..360 + 0: IDENT@359..360 "G" [] [] + 2: TS_TYPE_PARAMETERS@360..364 + 0: L_ANGLE@360..361 "<" [] [] + 1: TS_TYPE_PARAMETER_LIST@361..362 + 0: TS_TYPE_PARAMETER@361..362 + 0: TS_TYPE_PARAMETER_NAME@361..362 + 0: IDENT@361..362 "T" [] [] + 1: (empty) + 2: (empty) + 2: R_ANGLE@362..364 ">" [] [Whitespace(" ")] + 3: EQ@364..366 "=" [] [Whitespace(" ")] + 4: TS_CONDITIONAL_TYPE@366..421 + 0: TS_REFERENCE_TYPE@366..368 + 0: JS_REFERENCE_IDENTIFIER@366..368 + 0: IDENT@366..368 "T" [] [Whitespace(" ")] + 1: (empty) + 1: EXTENDS_KW@368..376 "extends" [] [Whitespace(" ")] + 2: TS_TUPLE_TYPE@376..410 + 0: L_BRACK@376..377 "[" [] [] + 1: TS_TUPLE_TYPE_ELEMENT_LIST@377..408 + 0: TS_UNKNOWN_TYPE@377..384 + 0: UNKNOWN_KW@377..384 "unknown" [] [] + 1: COMMA@384..386 "," [] [Whitespace(" ")] + 2: TS_INFER_TYPE@386..408 + 0: INFER_KW@386..392 "infer" [] [Whitespace(" ")] + 1: TS_TYPE_PARAMETER_NAME@392..394 + 0: IDENT@392..394 "S" [] [Whitespace(" ")] + 2: TS_TYPE_CONSTRAINT_CLAUSE@394..408 + 0: EXTENDS_KW@394..402 "extends" [] [Whitespace(" ")] + 1: TS_STRING_TYPE@402..408 + 0: STRING_KW@402..408 "string" [] [] + 2: R_BRACK@408..410 "]" [] [Whitespace(" ")] + 3: QUESTION@410..412 "?" [] [Whitespace(" ")] + 4: TS_REFERENCE_TYPE@412..414 + 0: JS_REFERENCE_IDENTIFIER@412..414 + 0: IDENT@412..414 "S" [] [Whitespace(" ")] + 1: (empty) + 5: COLON@414..416 ":" [] [Whitespace(" ")] + 6: TS_NEVER_TYPE@416..421 + 0: NEVER_KW@416..421 "never" [] [] + 5: SEMICOLON@421..422 ";" [] [] + 7: TS_TYPE_ALIAS_DECLARATION@422..476 + 0: TYPE_KW@422..428 "type" [Newline("\n")] [Whitespace(" ")] + 1: TS_IDENTIFIER_BINDING@428..430 + 0: IDENT@428..430 "H" [] [Whitespace(" ")] + 2: (empty) + 3: EQ@430..432 "=" [] [Whitespace(" ")] + 4: TS_CONDITIONAL_TYPE@432..475 + 0: TS_REFERENCE_TYPE@432..434 + 0: JS_REFERENCE_IDENTIFIER@432..434 + 0: IDENT@432..434 "A" [] [Whitespace(" ")] + 1: (empty) + 1: EXTENDS_KW@434..442 "extends" [] [Whitespace(" ")] + 2: TS_FUNCTION_TYPE@442..468 + 0: (empty) + 1: JS_PARAMETERS@442..445 + 0: L_PAREN@442..443 "(" [] [] + 1: JS_PARAMETER_LIST@443..443 + 2: R_PAREN@443..445 ")" [] [Whitespace(" ")] + 2: FAT_ARROW@445..448 "=>" [] [Whitespace(" ")] + 3: TS_CONDITIONAL_TYPE@448..468 + 0: TS_REFERENCE_TYPE@448..450 + 0: JS_REFERENCE_IDENTIFIER@448..450 + 0: IDENT@448..450 "B" [] [Whitespace(" ")] + 1: (empty) + 1: EXTENDS_KW@450..458 "extends" [] [Whitespace(" ")] + 2: TS_REFERENCE_TYPE@458..460 + 0: JS_REFERENCE_IDENTIFIER@458..460 + 0: IDENT@458..460 "C" [] [Whitespace(" ")] + 1: (empty) + 3: QUESTION@460..462 "?" [] [Whitespace(" ")] + 4: TS_REFERENCE_TYPE@462..464 + 0: JS_REFERENCE_IDENTIFIER@462..464 + 0: IDENT@462..464 "D" [] [Whitespace(" ")] + 1: (empty) + 5: COLON@464..466 ":" [] [Whitespace(" ")] + 6: TS_REFERENCE_TYPE@466..468 + 0: JS_REFERENCE_IDENTIFIER@466..468 + 0: IDENT@466..468 "E" [] [Whitespace(" ")] + 1: (empty) + 3: QUESTION@468..470 "?" [] [Whitespace(" ")] + 4: TS_REFERENCE_TYPE@470..472 + 0: JS_REFERENCE_IDENTIFIER@470..472 + 0: IDENT@470..472 "F" [] [Whitespace(" ")] + 1: (empty) + 5: COLON@472..474 ":" [] [Whitespace(" ")] + 6: TS_REFERENCE_TYPE@474..475 + 0: JS_REFERENCE_IDENTIFIER@474..475 + 0: IDENT@474..475 "G" [] [] + 1: (empty) + 5: SEMICOLON@475..476 ";" [] [] + 8: TS_TYPE_ALIAS_DECLARATION@476..553 + 0: TYPE_KW@476..482 "type" [Newline("\n")] [Whitespace(" ")] + 1: TS_IDENTIFIER_BINDING@482..483 + 0: IDENT@482..483 "J" [] [] + 2: TS_TYPE_PARAMETERS@483..487 + 0: L_ANGLE@483..484 "<" [] [] + 1: TS_TYPE_PARAMETER_LIST@484..485 + 0: TS_TYPE_PARAMETER@484..485 + 0: TS_TYPE_PARAMETER_NAME@484..485 + 0: IDENT@484..485 "T" [] [] + 1: (empty) + 2: (empty) + 2: R_ANGLE@485..487 ">" [] [Whitespace(" ")] + 3: EQ@487..489 "=" [] [Whitespace(" ")] + 4: TS_CONDITIONAL_TYPE@489..552 + 0: TS_REFERENCE_TYPE@489..491 + 0: JS_REFERENCE_IDENTIFIER@489..491 + 0: IDENT@489..491 "T" [] [Whitespace(" ")] + 1: (empty) + 1: EXTENDS_KW@491..499 "extends" [] [Whitespace(" ")] + 2: TS_PARENTHESIZED_TYPE@499..541 + 0: L_PAREN@499..500 "(" [] [] + 1: TS_FUNCTION_TYPE@500..539 + 0: (empty) + 1: JS_PARAMETERS@500..514 + 0: L_PAREN@500..501 "(" [] [] + 1: JS_PARAMETER_LIST@501..512 + 0: JS_REST_PARAMETER@501..512 + 0: DOT3@501..504 "..." [] [] + 1: JS_IDENTIFIER_BINDING@504..505 + 0: IDENT@504..505 "a" [] [] + 2: TS_TYPE_ANNOTATION@505..512 + 0: COLON@505..507 ":" [] [Whitespace(" ")] + 1: TS_ARRAY_TYPE@507..512 + 0: TS_ANY_TYPE@507..510 + 0: ANY_KW@507..510 "any" [] [] + 1: L_BRACK@510..511 "[" [] [] + 2: R_BRACK@511..512 "]" [] [] + 2: R_PAREN@512..514 ")" [] [Whitespace(" ")] + 2: FAT_ARROW@514..517 "=>" [] [Whitespace(" ")] + 3: TS_INFER_TYPE@517..539 + 0: INFER_KW@517..523 "infer" [] [Whitespace(" ")] + 1: TS_TYPE_PARAMETER_NAME@523..525 + 0: IDENT@523..525 "R" [] [Whitespace(" ")] + 2: TS_TYPE_CONSTRAINT_CLAUSE@525..539 + 0: EXTENDS_KW@525..533 "extends" [] [Whitespace(" ")] + 1: TS_STRING_TYPE@533..539 + 0: STRING_KW@533..539 "string" [] [] + 2: R_PAREN@539..541 ")" [] [Whitespace(" ")] + 3: QUESTION@541..543 "?" [] [Whitespace(" ")] + 4: TS_REFERENCE_TYPE@543..545 + 0: JS_REFERENCE_IDENTIFIER@543..545 + 0: IDENT@543..545 "R" [] [Whitespace(" ")] + 1: (empty) + 5: COLON@545..547 ":" [] [Whitespace(" ")] + 6: TS_NEVER_TYPE@547..552 + 0: NEVER_KW@547..552 "never" [] [] + 5: SEMICOLON@552..553 ";" [] [] + 3: EOF@553..554 "" [Newline("\n")] [] diff --git a/crates/rome_js_parser/test_data/inline/ok/ts_conditional_type.ts b/crates/rome_js_parser/test_data/inline/ok/ts_conditional_type.ts index a7904acd0f4..bfaa832020a 100644 --- a/crates/rome_js_parser/test_data/inline/ok/ts_conditional_type.ts +++ b/crates/rome_js_parser/test_data/inline/ok/ts_conditional_type.ts @@ -1,3 +1,9 @@ type A = number; type B = string extends number ? string : number; type C = A extends (B extends A ? number : string) ? void : number; +type D = T extends [infer S extends string, ...unknown[]] ? S : never; +type E = T extends (infer U extends number ? U : T ) ? U : T +type F = T extends { [P in infer U extends keyof T ? 1 : 0]: 1; } ? 1 : 0; +type G = T extends [unknown, infer S extends string] ? S : never; +type H = A extends () => B extends C ? D : E ? F : G; +type J = T extends ((...a: any[]) => infer R extends string) ? R : never; diff --git a/crates/rome_js_parser/test_data/inline/ok/ts_inferred_type.rast b/crates/rome_js_parser/test_data/inline/ok/ts_inferred_type.rast index 950922cdbcf..c79a0aa0750 100644 --- a/crates/rome_js_parser/test_data/inline/ok/ts_inferred_type.rast +++ b/crates/rome_js_parser/test_data/inline/ok/ts_inferred_type.rast @@ -11,9 +11,10 @@ JsModule { eq_token: EQ@7..9 "=" [] [Whitespace(" ")], ty: TsInferType { infer_token: INFER_KW@9..15 "infer" [] [Whitespace(" ")], - type_parameter: TsTypeParameterName { + name: TsTypeParameterName { ident_token: IDENT@15..16 "B" [] [], }, + constraint: missing (optional), }, semicolon_token: SEMICOLON@16..17 ";" [] [], }, @@ -37,9 +38,10 @@ JsModule { colon_token: COLON@30..32 ":" [] [Whitespace(" ")], ty: TsInferType { infer_token: INFER_KW@32..38 "infer" [] [Whitespace(" ")], - type_parameter: TsTypeParameterName { + name: TsTypeParameterName { ident_token: IDENT@38..39 "U" [] [], }, + constraint: missing (optional), }, }, separator_token: SEMICOLON@39..41 ";" [] [Whitespace(" ")], @@ -54,9 +56,10 @@ JsModule { colon_token: COLON@42..44 ":" [] [Whitespace(" ")], ty: TsInferType { infer_token: INFER_KW@44..50 "infer" [] [Whitespace(" ")], - type_parameter: TsTypeParameterName { + name: TsTypeParameterName { ident_token: IDENT@50..51 "U" [] [], }, + constraint: missing (optional), }, }, separator_token: missing (optional), @@ -84,6 +87,7 @@ JsModule { 0: INFER_KW@9..15 "infer" [] [Whitespace(" ")] 1: TS_TYPE_PARAMETER_NAME@15..16 0: IDENT@15..16 "B" [] [] + 2: (empty) 5: SEMICOLON@16..17 ";" [] [] 1: TS_TYPE_ALIAS_DECLARATION@17..53 0: TYPE_KW@17..23 "type" [Newline("\n")] [Whitespace(" ")] @@ -105,6 +109,7 @@ JsModule { 0: INFER_KW@32..38 "infer" [] [Whitespace(" ")] 1: TS_TYPE_PARAMETER_NAME@38..39 0: IDENT@38..39 "U" [] [] + 2: (empty) 4: SEMICOLON@39..41 ";" [] [Whitespace(" ")] 1: TS_PROPERTY_SIGNATURE_TYPE_MEMBER@41..51 0: (empty) @@ -117,6 +122,7 @@ JsModule { 0: INFER_KW@44..50 "infer" [] [Whitespace(" ")] 1: TS_TYPE_PARAMETER_NAME@50..51 0: IDENT@50..51 "U" [] [] + 2: (empty) 4: (empty) 2: R_CURLY@51..52 "}" [] [] 5: SEMICOLON@52..53 ";" [] [] diff --git a/crates/rome_js_syntax/src/generated/nodes.rs b/crates/rome_js_syntax/src/generated/nodes.rs index 908c726cc8e..379ee21e715 100644 --- a/crates/rome_js_syntax/src/generated/nodes.rs +++ b/crates/rome_js_syntax/src/generated/nodes.rs @@ -9461,15 +9461,19 @@ impl TsInferType { pub fn as_fields(&self) -> TsInferTypeFields { TsInferTypeFields { infer_token: self.infer_token(), - type_parameter: self.type_parameter(), + name: self.name(), + constraint: self.constraint(), } } pub fn infer_token(&self) -> SyntaxResult { support::required_token(&self.syntax, 0usize) } - pub fn type_parameter(&self) -> SyntaxResult { + pub fn name(&self) -> SyntaxResult { support::required_node(&self.syntax, 1usize) } + pub fn constraint(&self) -> Option { + support::node(&self.syntax, 2usize) + } } #[cfg(feature = "serde")] impl Serialize for TsInferType { @@ -9483,7 +9487,8 @@ impl Serialize for TsInferType { #[cfg_attr(feature = "serde", derive(Serialize))] pub struct TsInferTypeFields { pub infer_token: SyntaxResult, - pub type_parameter: SyntaxResult, + pub name: SyntaxResult, + pub constraint: Option, } #[derive(Clone, PartialEq, Eq, Hash)] pub struct TsInstantiationExpression { @@ -22678,9 +22683,10 @@ impl std::fmt::Debug for TsInferType { "infer_token", &support::DebugSyntaxResult(self.infer_token()), ) + .field("name", &support::DebugSyntaxResult(self.name())) .field( - "type_parameter", - &support::DebugSyntaxResult(self.type_parameter()), + "constraint", + &support::DebugOptionalElement(self.constraint()), ) .finish() } diff --git a/crates/rome_js_syntax/src/generated/nodes_mut.rs b/crates/rome_js_syntax/src/generated/nodes_mut.rs index 671ec142ee1..cbf59e5233a 100644 --- a/crates/rome_js_syntax/src/generated/nodes_mut.rs +++ b/crates/rome_js_syntax/src/generated/nodes_mut.rs @@ -4687,12 +4687,18 @@ impl TsInferType { .splice_slots(0usize..=0usize, once(Some(element.into()))), ) } - pub fn with_type_parameter(self, element: TsTypeParameterName) -> Self { + pub fn with_name(self, element: TsTypeParameterName) -> Self { Self::unwrap_cast( self.syntax .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), ) } + pub fn with_constraint(self, element: Option) -> Self { + Self::unwrap_cast(self.syntax.splice_slots( + 2usize..=2usize, + once(element.map(|element| element.into_syntax().into())), + )) + } } impl TsInstantiationExpression { pub fn with_expression(self, element: AnyJsExpression) -> Self { diff --git a/xtask/codegen/js.ungram b/xtask/codegen/js.ungram index ffbfe09b12c..97ac5fd9cb7 100644 --- a/xtask/codegen/js.ungram +++ b/xtask/codegen/js.ungram @@ -1836,7 +1836,8 @@ TsTypeOperatorType = // ^^^^^^^ ^^^^^^^ TsInferType = 'infer' - type_parameter: TsTypeParameterName + name: TsTypeParameterName + constraint: TsTypeConstraintClause? TsFunctionType = type_parameters: TsTypeParameters?