fix(isolated-declarations): inferring of UnrayExpression incorrectly (#3920)

close: #3914
This commit is contained in:
Dunqing 2024-06-26 07:21:35 +00:00
parent 3db2553dc2
commit 59ce38bb85
5 changed files with 75 additions and 6 deletions

View file

@ -104,6 +104,10 @@ impl<'a> Expression<'a> {
matches!(self, Self::StringLiteral(_) | Self::TemplateLiteral(_))
}
pub fn is_number_literal(&self) -> bool {
matches!(self, Self::NumericLiteral(_) | Self::BigIntLiteral(_))
}
pub fn is_specific_string_literal(&self, string: &str) -> bool {
match self {
Self::StringLiteral(s) => s.value == string,

View file

@ -1,7 +1,7 @@
use oxc_allocator::Box;
use oxc_ast::ast::{
ArrowFunctionExpression, BindingPatternKind, Expression, FormalParameter, Function, Statement,
TSType, TSTypeAnnotation,
TSType, TSTypeAnnotation, UnaryExpression,
};
use oxc_span::{GetSpan, SPAN};
@ -14,6 +14,10 @@ use crate::{
};
impl<'a> IsolatedDeclarations<'a> {
pub fn can_infer_unary_expression(expr: &UnaryExpression<'a>) -> bool {
expr.operator.is_arithmetic() && expr.argument.is_number_literal()
}
pub fn infer_type_from_expression(&self, expr: &Expression<'a>) -> Option<TSType<'a>> {
match expr {
Expression::BooleanLiteral(_) => Some(self.ast.ts_boolean_keyword(SPAN)),
@ -66,6 +70,13 @@ impl<'a> IsolatedDeclarations<'a> {
self.infer_type_from_expression(&expr.expression)
}
Expression::TSTypeAssertion(expr) => Some(self.ast.copy(&expr.type_annotation)),
Expression::UnaryExpression(expr) => {
if Self::can_infer_unary_expression(expr) {
self.infer_type_from_expression(&expr.argument)
} else {
None
}
}
_ => None,
}
}
@ -136,12 +147,13 @@ impl<'a> IsolatedDeclarations<'a> {
.map(|type_annotation| self.ast.ts_type_annotation(SPAN, type_annotation))
}
pub fn is_need_to_infer_type_from_expression(expr: &Expression) -> bool {
pub fn is_need_to_infer_type_from_expression(expr: &Expression<'a>) -> bool {
match expr {
Expression::NumericLiteral(_)
| Expression::BigIntLiteral(_)
| Expression::StringLiteral(_) => false,
Expression::TemplateLiteral(lit) => !lit.expressions.is_empty(),
Expression::UnaryExpression(expr) => !Self::can_infer_unary_expression(expr),
_ => true,
}
}

View file

@ -192,9 +192,16 @@ impl<'a> IsolatedDeclarations<'a> {
Expression::TemplateLiteral(lit) => self
.transform_template_to_string(lit)
.map(|string| self.ast.ts_literal_type(lit.span, TSLiteral::StringLiteral(string))),
Expression::UnaryExpression(expr) => Some(
self.ast.ts_literal_type(SPAN, TSLiteral::UnaryExpression(self.ast.copy(expr))),
),
Expression::UnaryExpression(expr) => {
if Self::can_infer_unary_expression(expr) {
Some(
self.ast
.ts_literal_type(SPAN, TSLiteral::UnaryExpression(self.ast.copy(expr))),
)
} else {
None
}
}
Expression::ArrayExpression(expr) => {
Some(self.transform_array_expression_to_ts_type(expr, true))
}

View file

@ -1,5 +1,18 @@
// Correct
// ParenthesizedExpression
const n = (0);
const s = ("");
const t = (``);
const b = (true);
const b = (true);
// UnaryExpression
let unaryA = +12;
const unaryB = -1_2n;
// Incorrect
// UnaryExpression
const unaryC = +"str"
const unaryD = typeof "str"
const unaryE = {E: -"str"} as const

View file

@ -8,3 +8,36 @@ declare const n: number;
declare const s: string;
declare const t: string;
declare const b: boolean;
declare let unaryA: number;
declare const unaryB = -1_2n;
declare const unaryC: unknown;
declare const unaryD: unknown;
declare const unaryE: {};
==================== Errors ====================
x TS9010: Variable must have an explicit type annotation with
| --isolatedDeclarations.
,-[16:7]
15 | // UnaryExpression
16 | const unaryC = +"str"
: ^^^^^^
17 | const unaryD = typeof "str"
`----
x TS9010: Variable must have an explicit type annotation with
| --isolatedDeclarations.
,-[17:7]
16 | const unaryC = +"str"
17 | const unaryD = typeof "str"
: ^^^^^^
18 | const unaryE = {E: -"str"} as const
`----
x TS9013: Expression type can't be inferred with --isolatedDeclarations.
,-[18:20]
17 | const unaryD = typeof "str"
18 | const unaryE = {E: -"str"} as const
: ^^^^^^
`----