From 06a1df69907c8143192677d61a7fde114ec63a1b Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Mon, 22 Sep 2025 04:24:15 +0000 Subject: [PATCH] feat(formatter): implement formatting for `TSTypeParameters` and `TSTypeParameterInstantiation` (#13919) --- .../src/write/arrow_function_expression.rs | 15 +- crates/oxc_formatter/src/write/class.rs | 6 +- crates/oxc_formatter/src/write/function.rs | 1 + crates/oxc_formatter/src/write/mod.rs | 43 +--- .../src/write/type_parameters.rs | 213 +++++++++++++++++- .../snapshots/formatter_typescript.snap | 4 +- .../snapshots/prettier.ts.snap.md | 72 ++---- 7 files changed, 240 insertions(+), 114 deletions(-) diff --git a/crates/oxc_formatter/src/write/arrow_function_expression.rs b/crates/oxc_formatter/src/write/arrow_function_expression.rs index d836d466e3950..440b7b278d6da 100644 --- a/crates/oxc_formatter/src/write/arrow_function_expression.rs +++ b/crates/oxc_formatter/src/write/arrow_function_expression.rs @@ -855,22 +855,15 @@ fn format_signature<'a, 'b>( cache_mode: FunctionBodyCacheMode, ) -> impl Format<'a> + 'b { format_with(move |f| { - let formatted_async_token = - format_with(|f| if arrow.r#async() { write!(f, ["async", space()]) } else { Ok(()) }); - - let formatted_parameters = - format_with(|f| write!(f, [arrow.type_parameters(), arrow.params()])); - - let format_return_type = format_with(|f| write!(f, arrow.return_type())); - let signatures = format_once(|f| { write!( f, [group(&format_args!( maybe_space(!is_first_in_chain), - formatted_async_token, - group(&formatted_parameters), - group(&format_return_type) + arrow.r#async().then_some("async "), + arrow.type_parameters(), + arrow.params(), + group(&arrow.return_type()) ))] ) }); diff --git a/crates/oxc_formatter/src/write/class.rs b/crates/oxc_formatter/src/write/class.rs index e4a9887d2ca9b..7b792afa8f92c 100644 --- a/crates/oxc_formatter/src/write/class.rs +++ b/crates/oxc_formatter/src/write/class.rs @@ -27,7 +27,7 @@ use crate::{ use super::{ FormatWrite, - type_parameters::{FormatTsTypeParameters, FormatTsTypeParametersOptions}, + type_parameters::{FormatTSTypeParameters, FormatTSTypeParametersOptions}, }; impl<'a> FormatWrite<'a> for AstNode<'a, ClassBody<'a>> { @@ -314,9 +314,9 @@ impl<'a> Format<'a> for FormatClass<'a, '_> { if let Some(type_parameters) = &type_parameters { write!( f, - FormatTsTypeParameters::new( + FormatTSTypeParameters::new( type_parameters, - FormatTsTypeParametersOptions { + FormatTSTypeParametersOptions { group_id: type_parameters_id, is_type_or_interface_decl: false } diff --git a/crates/oxc_formatter/src/write/function.rs b/crates/oxc_formatter/src/write/function.rs index 909148c9cd8ec..b8297f2ebe8c3 100644 --- a/crates/oxc_formatter/src/write/function.rs +++ b/crates/oxc_formatter/src/write/function.rs @@ -49,6 +49,7 @@ impl<'a> FormatWrite<'a> for FormatFunction<'a, '_> { if self.r#async() { write!(f, ["async", space()])?; } + write!( f, [ diff --git a/crates/oxc_formatter/src/write/mod.rs b/crates/oxc_formatter/src/write/mod.rs index fabe789224569..be07199b6632d 100644 --- a/crates/oxc_formatter/src/write/mod.rs +++ b/crates/oxc_formatter/src/write/mod.rs @@ -78,7 +78,7 @@ use self::{ object_pattern_like::ObjectPatternLike, parameter_list::{ParameterLayout, ParameterList}, semicolon::{ClassPropertySemicolon, OptionalSemicolon}, - type_parameters::{FormatTsTypeParameters, FormatTsTypeParametersOptions}, + type_parameters::{FormatTSTypeParameters, FormatTSTypeParametersOptions}, utils::{ array::{TrailingSeparatorMode, write_array_node}, statement_body::FormatStatementBody, @@ -1377,44 +1377,9 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSQualifiedName<'a>> { } } -impl<'a> FormatWrite<'a> for AstNode<'a, TSTypeParameterInstantiation<'a>> { - fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { - write!(f, "<")?; - for (i, param) in self.params().iter().enumerate() { - if i != 0 { - write!(f, [",", space()])?; - } - write!(f, param)?; - } - write!(f, ">") - } -} - -impl<'a> FormatWrite<'a> for AstNode<'a, TSTypeParameter<'a>> { - fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { - if self.r#const() { - write!(f, ["const", space()])?; - } - if self.r#in() { - write!(f, ["in", space()])?; - } - if self.out() { - write!(f, ["out", space()])?; - } - write!(f, self.name())?; - if let Some(constraint) = &self.constraint() { - write!(f, [space(), "extends", space(), constraint])?; - } - if let Some(default) = &self.default() { - write!(f, [space(), "=", space(), default])?; - } - Ok(()) - } -} - impl<'a> FormatWrite<'a> for AstNode<'a, TSTypeParameterDeclaration<'a>> { fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { - write!(f, ["<", self.params(), ">"]) + FormatTSTypeParameters::new(self, FormatTSTypeParametersOptions::default()).fmt(f) } } @@ -1463,9 +1428,9 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSInterfaceDeclaration<'a>> { if let Some(type_parameters) = type_parameters { write!( f, - FormatTsTypeParameters::new( + FormatTSTypeParameters::new( type_parameters, - FormatTsTypeParametersOptions { + FormatTSTypeParametersOptions { group_id: type_parameter_group, is_type_or_interface_decl: true } diff --git a/crates/oxc_formatter/src/write/type_parameters.rs b/crates/oxc_formatter/src/write/type_parameters.rs index b410f77dc8467..0157483faa2ea 100644 --- a/crates/oxc_formatter/src/write/type_parameters.rs +++ b/crates/oxc_formatter/src/write/type_parameters.rs @@ -1,3 +1,5 @@ +use std::fmt::Pointer; + use oxc_allocator::{Address, Vec}; use oxc_ast::{AstKind, ast::*}; @@ -9,9 +11,49 @@ use crate::{ }, generated::ast_nodes::{AstNode, AstNodes}, options::{FormatTrailingCommas, TrailingSeparator}, + utils::call_expression::is_test_call_expression, write, }; +use super::FormatWrite; + +impl<'a> FormatWrite<'a> for AstNode<'a, TSTypeParameter<'a>> { + fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { + if self.r#const() { + write!(f, ["const", space()])?; + } + if self.r#in() { + write!(f, ["in", space()])?; + } + if self.out() { + write!(f, ["out", space()])?; + } + write!(f, self.name())?; + + if let Some(constraint) = &self.constraint() { + let group_id = f.group_id("constraint"); + + write!( + f, + [ + space(), + "extends", + group(&indent(&format_args!( + line_suffix_boundary(), + soft_line_break_or_space() + ))) + .with_group_id(Some(group_id)), + indent_if_group_breaks(&constraint, group_id) + ] + )?; + } + if let Some(default) = &self.default() { + write!(f, [space(), "=", space(), default])?; + } + Ok(()) + } +} + impl<'a> Format<'a> for AstNode<'a, Vec<'a, TSTypeParameter<'a>>> { fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { // Type parameter lists of arrow function expressions have to include at least one comma @@ -37,35 +79,190 @@ impl<'a> Format<'a> for AstNode<'a, Vec<'a, TSTypeParameter<'a>>> { } } -pub struct FormatTsTypeParametersOptions { +#[derive(Default)] +pub struct FormatTSTypeParametersOptions { pub group_id: Option, pub is_type_or_interface_decl: bool, } -pub struct FormatTsTypeParameters<'a, 'b> { +pub struct FormatTSTypeParameters<'a, 'b> { decl: &'b AstNode<'a, TSTypeParameterDeclaration<'a>>, - options: FormatTsTypeParametersOptions, + options: FormatTSTypeParametersOptions, } -impl<'a, 'b> FormatTsTypeParameters<'a, 'b> { +impl<'a, 'b> FormatTSTypeParameters<'a, 'b> { pub fn new( decl: &'b AstNode<'a, TSTypeParameterDeclaration<'a>>, - options: FormatTsTypeParametersOptions, + options: FormatTSTypeParametersOptions, ) -> Self { Self { decl, options } } } -impl<'a> Format<'a> for FormatTsTypeParameters<'a, '_> { +impl<'a> Format<'a> for FormatTSTypeParameters<'a, '_> { fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { - if self.decl.params().is_empty() && self.options.is_type_or_interface_decl { + let params = self.decl.params(); + if params.is_empty() && self.options.is_type_or_interface_decl { write!(f, "<>") } else { write!( f, - [group(&format_args!("<", soft_block_indent(&self.decl.params()), ">")) + [group(&format_args!("<", format_once(|f| { + if matches!( self.decl.parent.parent().parent(), AstNodes::CallExpression(call) if is_test_call_expression(call)) + { + f.join_nodes_with_space().entries_with_trailing_separator(params, ",", TrailingSeparator::Omit).finish() + } else { + soft_block_indent(¶ms).fmt(f) + } + }), ">")) .with_group_id(self.options.group_id)] ) } } } + +impl<'a> FormatWrite<'a> for AstNode<'a, TSTypeParameterInstantiation<'a>> { + fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> { + let params = self.params(); + + if params.is_empty() { + // This shouldn't happen in valid TypeScript code, but handle it gracefully + return write!( + f, + [&group(&format_args!( + "<", + format_dangling_comments(self.span).with_soft_block_indent(), + ">" + ))] + ); + } + + // Check if this is in the context of an arrow function variable + let is_arrow_function_vars = is_arrow_function_variable_type_argument(self); + + // Check if the first (and only) argument can be hugged + let first_arg_can_be_hugged = if params.len() == 1 { + if let Some(first_type) = params.first() { + matches!(first_type.as_ref(), TSType::TSNullKeyword(_)) + || should_hug_single_type(first_type.as_ref()) + } else { + false + } + } else { + false + }; + + let format_params = format_once(|f| { + f.join_with(&soft_line_break_or_space()) + .entries_with_trailing_separator(params, ",", TrailingSeparator::Disallowed) + .finish() + }); + + let should_inline = + !is_arrow_function_vars && (params.is_empty() || first_arg_can_be_hugged); + + if should_inline { + write!(f, ["<", format_params, ">"]) + } else { + write!(f, [group(&format_args!("<", soft_block_indent(&format_params), ">"))]) + } + } +} + +/// Check if a TSType is a simple type (primitives, keywords, simple references) +fn is_simple_type(ty: &TSType) -> bool { + match ty { + TSType::TSAnyKeyword(_) + | TSType::TSNullKeyword(_) + | TSType::TSThisType(_) + | TSType::TSVoidKeyword(_) + | TSType::TSNumberKeyword(_) + | TSType::TSBooleanKeyword(_) + | TSType::TSBigIntKeyword(_) + | TSType::TSStringKeyword(_) + | TSType::TSSymbolKeyword(_) + | TSType::TSNeverKeyword(_) + | TSType::TSObjectKeyword(_) + | TSType::TSUndefinedKeyword(_) + | TSType::TSTemplateLiteralType(_) + | TSType::TSLiteralType(_) + | TSType::TSUnknownKeyword(_) => true, + TSType::TSTypeReference(reference) => { + // Simple reference without type arguments + reference.type_arguments.is_none() + } + _ => false, + } +} + +/// Check if a TSType is object-like (object literal, mapped type, etc.) +fn is_object_like_type(ty: &TSType) -> bool { + matches!(ty, TSType::TSTypeLiteral(_) | TSType::TSMappedType(_)) +} + +/// Check if a single type should be "hugged" (kept inline) +fn should_hug_single_type(ty: &TSType) -> bool { + // Simple types and object-like types can be hugged + if is_simple_type(ty) || is_object_like_type(ty) { + return true; + } + + // Check for union types with mostly void types and one object type + // (e.g., `SomeType`) + if let TSType::TSUnionType(union_type) = ty { + let types = &union_type.types; + + // Must have at least 2 types + if types.len() < 2 { + return types.len() == 1 && should_hug_single_type(&types[0]); + } + + let has_object_type = types + .iter() + .any(|t| matches!(t, TSType::TSTypeLiteral(_) | TSType::TSTypeReference(_))); + + let void_count = types + .iter() + .filter(|t| { + matches!( + t, + TSType::TSVoidKeyword(_) + | TSType::TSNullKeyword(_) + | TSType::TSUndefinedKeyword(_) + ) + }) + .count(); + + // Union is huggable if it's mostly void types with one object/reference type + (types.len() - 1 == void_count && has_object_type) || types.len() == 1 + } else { + false + } +} + +/// Check if this type parameter instantiation is in an arrow function variable context +/// +/// This detects patterns like: +/// ```typescript +/// const foo: SomeThing<{ [P in "x" | "y"]: number }> = () => {}; +/// ``` +fn is_arrow_function_variable_type_argument<'a>( + node: &AstNode<'a, TSTypeParameterInstantiation<'a>>, +) -> bool { + let Some(first) = node.params().first() else { unreachable!() }; + + // Skip check for single object-like types + if node.params().len() == 1 && is_object_like_type(first.as_ref()) { + return false; + } + + matches!( + &node.parent, + AstNodes::TSTypeAnnotation(type_annotation) + if matches!( + &type_annotation.parent, + AstNodes::VariableDeclarator(var_decl) + if matches!(&var_decl.init, Some(Expression::ArrowFunctionExpression(_))) + ) + ) +} diff --git a/tasks/coverage/snapshots/formatter_typescript.snap b/tasks/coverage/snapshots/formatter_typescript.snap index eadf1f8b975b2..2d5aa390c2d7f 100644 --- a/tasks/coverage/snapshots/formatter_typescript.snap +++ b/tasks/coverage/snapshots/formatter_typescript.snap @@ -2,7 +2,7 @@ commit: 261630d6 formatter_typescript Summary: AST Parsed : 8816/8816 (100.00%) -Positive Passed: 8788/8816 (99.68%) +Positive Passed: 8789/8816 (99.69%) Mismatch: tasks/coverage/typescript/tests/cases/compiler/amdLikeInputDeclarationEmit.ts Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/arrayFromAsync.ts @@ -15,8 +15,6 @@ Mismatch: tasks/coverage/typescript/tests/cases/compiler/complexNarrowingWithAny Mismatch: tasks/coverage/typescript/tests/cases/compiler/declarationEmitCastReusesTypeNode4.ts -Mismatch: tasks/coverage/typescript/tests/cases/compiler/declarationEmitShadowingInferNotRenamed.ts - Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/genericTypeAssertions3.ts Unexpected token Mismatch: tasks/coverage/typescript/tests/cases/compiler/jsxNamespaceGlobalReexport.tsx diff --git a/tasks/prettier_conformance/snapshots/prettier.ts.snap.md b/tasks/prettier_conformance/snapshots/prettier.ts.snap.md index 40a1df72c7e0f..b409019775cf2 100644 --- a/tasks/prettier_conformance/snapshots/prettier.ts.snap.md +++ b/tasks/prettier_conformance/snapshots/prettier.ts.snap.md @@ -1,4 +1,4 @@ -ts compatibility: 419/573 (73.12%) +ts compatibility: 447/573 (78.01%) # Failed @@ -13,15 +13,12 @@ ts compatibility: 419/573 (73.12%) | typescript/angular-component-examples/15934-computed.component.ts | 💥💥 | 76.92% | | typescript/angular-component-examples/15934.component.ts | 💥💥 | 53.85% | | typescript/angular-component-examples/test.component.ts | 💥💥 | 41.18% | -| typescript/argument-expansion/arrow-with-return-type.ts | 💥 | 89.47% | | typescript/arrow/16067.ts | 💥💥 | 95.92% | | typescript/arrow/comments.ts | 💥✨ | 44.44% | -| typescript/as/as.ts | 💥 | 89.06% | +| typescript/as/as.ts | 💥 | 96.18% | | typescript/as/expression-statement.ts | 💥 | 75.00% | -| typescript/assignment/issue-10846.ts | 💥 | 57.14% | -| typescript/assignment/issue-10848.tsx | 💥 | 52.12% | +| typescript/assignment/issue-10848.tsx | 💥 | 63.86% | | typescript/assignment/issue-10850.ts | 💥 | 50.00% | -| typescript/cast/generic-cast.ts | 💥 | 81.48% | | typescript/cast/tuple-and-record.ts | 💥 | 0.00% | | typescript/chain-expression/call-expression.ts | 💥 | 68.75% | | typescript/chain-expression/member-expression.ts | 💥 | 65.67% | @@ -29,7 +26,6 @@ ts compatibility: 419/573 (73.12%) | typescript/chain-expression/test2.ts | 💥 | 56.25% | | typescript/class/constructor.ts | 💥 | 96.15% | | typescript/class/empty-method-body.ts | 💥 | 80.00% | -| typescript/class/extends_implements.ts | 💥 | 86.30% | | typescript/class/quoted-property.ts | 💥 | 66.67% | | typescript/comments/16065.ts | 💥 | 63.64% | | typescript/comments/16207.ts | 💥 | 71.43% | @@ -38,25 +34,22 @@ ts compatibility: 419/573 (73.12%) | typescript/comments/location.ts | 💥 | 95.00% | | typescript/comments/mapped_types.ts | 💥 | 58.82% | | typescript/comments/method_types.ts | 💥 | 79.49% | -| typescript/comments/type-parameters.ts | 💥 | 36.36% | +| typescript/comments/type-parameters.ts | 💥 | 65.52% | | typescript/comments/type_literals.ts | 💥 | 68.97% | -| typescript/comments/union.ts | 💥 | 75.00% | +| typescript/comments/union.ts | 💥 | 83.33% | | typescript/compiler/anyIsAssignableToObject.ts | 💥 | 75.00% | | typescript/compiler/contextualSignatureInstantiation2.ts | 💥 | 88.89% | | typescript/compiler/indexSignatureWithInitializer.ts | 💥 | 75.00% | -| typescript/compiler/mappedTypeWithCombinedTypeMappers.ts | 💥 | 91.89% | | typescript/compiler/privacyGloImport.ts | 💥 | 99.32% | | typescript/conditional-types/comments.ts | 💥💥 | 60.21% | -| typescript/conditional-types/conditonal-types.ts | 💥💥 | 75.60% | -| typescript/conditional-types/infer-type.ts | 💥💥 | 39.38% | +| typescript/conditional-types/conditonal-types.ts | 💥💥 | 82.25% | +| typescript/conditional-types/infer-type.ts | 💥💥 | 43.22% | | typescript/conditional-types/nested-in-condition.ts | 💥✨ | 15.79% | -| typescript/conditional-types/new-ternary-spec.ts | 💥💥 | 47.09% | -| typescript/conditional-types/parentheses.ts | 💥💥 | 53.71% | +| typescript/conditional-types/new-ternary-spec.ts | 💥💥 | 52.64% | +| typescript/conditional-types/parentheses.ts | 💥💥 | 60.24% | | typescript/conformance/ambient/ambientDeclarations.ts | 💥 | 61.54% | | typescript/conformance/classes/mixinAccessModifiers.ts | 💥 | 99.07% | -| typescript/conformance/classes/mixinClassesAnnotated.ts | 💥 | 98.57% | | typescript/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractMixedWithModifiers.ts | 💥 | 86.67% | -| typescript/conformance/classes/classDeclarations/classHeritageSpecification/classExtendingClass.ts | 💥 | 96.77% | | typescript/conformance/es6/Symbols/symbolProperty15.ts | 💥 | 73.33% | | typescript/conformance/types/ambient/ambientDeclarations.ts | 💥 | 90.00% | | typescript/conformance/types/functions/functionOverloadCompatibilityWithVoid01.ts | 💥 | 75.00% | @@ -65,18 +58,14 @@ ts compatibility: 419/573 (73.12%) | typescript/conformance/types/functions/functionOverloadErrorsSyntax.ts | 💥 | 0.00% | | typescript/conformance/types/namespaceExportDeclaration/exportAsNamespace.d.ts | 💥 | 75.00% | | typescript/conformance/types/tuple/wideningTuples1.ts | 💥 | 80.00% | -| typescript/conformance/types/typeParameters/typeParameterLists/innerTypeParameterShadowingOuterOne2.ts | 💥 | 93.33% | | typescript/custom/abstract/abstractProperties.ts | 💥 | 75.00% | | typescript/custom/computedProperties/string.ts | 💥 | 73.33% | | typescript/custom/declare/declareModifier.d.ts | 💥 | 88.89% | | typescript/custom/modifiers/minustoken.ts | 💥 | 20.00% | | typescript/custom/modifiers/question.ts | 💥 | 0.00% | | typescript/custom/modifiers/readonly.ts | 💥 | 0.00% | -| typescript/custom/typeParameters/callAndConstructSignatureLong.ts | 💥 | 18.18% | -| typescript/custom/typeParameters/functionTypeLong.ts | 💥 | 50.00% | -| typescript/custom/typeParameters/typeParametersLong.ts | 💥 | 0.00% | | typescript/declare/declare_function.ts | 💥 | 44.44% | -| typescript/declare/object-type-in-declare-function.ts | 💥 | 64.71% | +| typescript/declare/object-type-in-declare-function.ts | 💥 | 43.75% | | typescript/declare/trailing-comma/function-rest-trailing-comma.ts | 💥💥💥 | 50.00% | | typescript/decorators/comments.ts | 💥 | 60.00% | | typescript/decorators/decorators-comments.ts | 💥 | 65.71% | @@ -89,72 +78,55 @@ ts compatibility: 419/573 (73.12%) | typescript/export/export.ts | 💥 | 85.71% | | typescript/function-type/consistent.ts | 💥 | 70.83% | | typescript/function-type/type-annotation.ts | 💥 | 0.00% | -| typescript/generic/arrow-return-type.ts | 💥 | 79.25% | -| typescript/generic/issue-6899.ts | 💥 | 21.05% | -| typescript/generic/object-method.ts | 💥 | 72.73% | | typescript/index-signature/static.ts | 💥 | 66.67% | -| typescript/infer-extends/basic.ts | 💥 | 71.43% | +| typescript/infer-extends/basic.ts | 💥 | 90.48% | | typescript/interface/comments-generic.ts | 💥💥 | 30.00% | | typescript/interface/ignore.ts | 💥💥 | 88.26% | -| typescript/interface/long-type-parameters/long-type-parameters.ts | 💥💥 | 43.05% | | typescript/interface2/comments-declare.ts | 💥 | 66.67% | | typescript/interface2/comments.ts | 💥 | 78.87% | -| typescript/interface2/break/break.ts | 💥💥💥 | 80.23% | | typescript/intersection/intersection-parens.ts | 💥💥 | 72.25% | -| typescript/intersection/type-arguments.ts | 💥💥 | 46.67% | | typescript/intersection/consistent-with-flow/intersection-parens.ts | 💥 | 69.77% | -| typescript/key-remapping-in-mapped-types/key-remapping.ts | 💥 | 23.53% | -| typescript/keyword-types/conditional-types.ts | 💥 | 87.50% | -| typescript/keywords/keywords-2.ts | 💥 | 79.41% | +| typescript/key-remapping-in-mapped-types/key-remapping.ts | 💥 | 55.56% | | typescript/last-argument-expansion/decorated-function.tsx | 💥 | 29.06% | | typescript/mapped-type/intersection.ts | 💥 | 0.00% | | typescript/mapped-type/issue-11098.ts | 💥 | 60.00% | | typescript/mapped-type/break-mode/break-mode.ts | 💥 | 40.00% | +| typescript/method/issue-10352-consistency.ts | 💥 | 63.64% | | typescript/method/semi.ts | 💥 | 42.86% | | typescript/module/global.ts | 💥 | 75.00% | | typescript/module/namespace_function.ts | 💥 | 66.67% | | typescript/multiparser-css/issue-6259.ts | 💥 | 57.14% | -| typescript/new/new-signature.ts | 💥 | 93.85% | | typescript/non-null/optional-chain.ts | 💥 | 72.22% | | typescript/non-null/parens.ts | 💥 | 96.00% | | typescript/nosemi/index-signature.ts | 💥 | 75.00% | | typescript/object-multiline/multiline.ts | 💥✨ | 23.21% | | typescript/optional-type/complex.ts | 💥 | 0.00% | -| typescript/optional-variance/basic.ts | 💥 | 81.97% | -| typescript/optional-variance/with-jsx.tsx | 💥 | 81.97% | +| typescript/optional-variance/basic.ts | 💥 | 98.36% | +| typescript/optional-variance/with-jsx.tsx | 💥 | 98.36% | | typescript/override-modifiers/override-modifier.ts | 💥 | 25.00% | | typescript/prettier-ignore/mapped-types.ts | 💥 | 54.72% | | typescript/prettier-ignore/prettier-ignore-nested-unions.ts | 💥 | 29.17% | | typescript/prettier-ignore/prettier-ignore-parenthesized-type.ts | 💥 | 0.00% | | typescript/rest-type/complex.ts | 💥 | 0.00% | -| typescript/rest-type/infer-type.ts | 💥 | 80.00% | +| typescript/rest-type/infer-type.ts | 💥 | 64.00% | | typescript/satisfies-operators/expression-statement.ts | 💥💥 | 78.38% | | typescript/satisfies-operators/lhs.ts | 💥✨ | 35.00% | -| typescript/template-literal-types/template-literal-types.ts | 💥 | 80.00% | -| typescript/test-declarations/test_declarations.ts | 💥💥 | 66.67% | -| typescript/trailing-comma/arrow-functions.tsx | 💥💥💥 | 25.00% | -| typescript/trailing-comma/type-arguments.ts | 💥💥💥 | 10.53% | -| typescript/trailing-comma/type-parameters-vs-arguments.ts | 💥💥💥 | 66.67% | +| typescript/template-literal-types/template-literal-types.ts | 💥 | 93.33% | | typescript/tuple/dangling-comments.ts | 💥💥💥 | 21.28% | | typescript/tuple/trailing-comma-for-empty-tuples.ts | 💥💥💥 | 16.67% | | typescript/tuple/trailing-comma-trailing-rest.ts | 💥💥💥 | 0.00% | | typescript/tuple/trailing-comma.ts | 💥💥💥 | 61.54% | | typescript/tuple/tuple.ts | 💥💥💥 | 0.00% | -| typescript/type-alias/conditional.ts | 💥 | 22.58% | -| typescript/type-alias/issue-100857.ts | 💥 | 67.61% | +| typescript/type-alias/conditional.ts | 💥 | 38.10% | | typescript/type-alias/issue-9874.ts | 💥 | 0.00% | | typescript/type-arguments-bit-shift-left-like/3.ts | 💥 | 0.00% | | typescript/type-arguments-bit-shift-left-like/5.tsx | 💥 | 0.00% | | typescript/typeof/typeof.ts | 💥 | 25.00% | -| typescript/typeparams/const.ts | 💥 | 86.15% | -| typescript/typeparams/line-breaking-after-extends-2.ts | 💥 | 20.00% | -| typescript/typeparams/line-breaking-after-extends.ts | 💥 | 17.14% | -| typescript/typeparams/long-function-arg.ts | 💥 | 76.92% | -| typescript/typeparams/empty-parameters-with-arrow-function/issue-13817.ts | 💥 | 66.67% | -| typescript/typeparams/trailing-comma/type-paramters.ts | 💥💥💥 | 28.57% | -| typescript/union/inlining.ts | 💥 | 77.37% | +| typescript/typeparams/const.ts | 💥 | 96.88% | +| typescript/typeparams/line-breaking-after-extends-2.ts | 💥 | 93.94% | +| typescript/typeparams/empty-parameters-with-arrow-function/issue-13817.ts | 💥 | 73.68% | +| typescript/union/inlining.ts | 💥 | 79.70% | | typescript/union/union-parens.ts | 💥 | 92.59% | -| typescript/union/with-type-params.ts | 💥 | 37.50% | | typescript/union/consistent-with-flow/prettier-ignore.ts | 💥 | 38.30% | | typescript/union/consistent-with-flow/within-tuple.ts | 💥 | 17.50% | | typescript/union/single-type/single-type.ts | 💥 | 66.67% |