feat(isolated-declarations): improve the inference template literal (#3797)

This commit is contained in:
Dunqing 2024-06-20 15:02:45 +00:00
parent b0d7355c98
commit a37138f1ec
7 changed files with 79 additions and 28 deletions

View file

@ -73,7 +73,12 @@ impl<'a> IsolatedDeclarations<'a> {
if let Some(init_expr) = &decl.init {
// if kind is const and it doesn't need to infer type from expression
if decl.kind.is_const() && !Self::is_need_to_infer_type_from_expression(init_expr) {
init = Some(self.ast.copy(init_expr));
if let Expression::TemplateLiteral(lit) = init_expr {
init =
self.transform_template_to_string(lit).map(Expression::StringLiteral);
} else {
init = Some(self.ast.copy(init_expr));
}
} else {
// otherwise, we need to infer type from expression
binding_type = self.infer_type_from_expression(init_expr);

View file

@ -21,8 +21,13 @@ impl<'a> IsolatedDeclarations<'a> {
Expression::NumericLiteral(_) | Expression::BigintLiteral(_) => {
Some(self.ast.ts_number_keyword(SPAN))
}
Expression::StringLiteral(_) | Expression::TemplateLiteral(_) => {
Some(self.ast.ts_string_keyword(SPAN))
Expression::StringLiteral(_) => Some(self.ast.ts_string_keyword(SPAN)),
Expression::TemplateLiteral(lit) => {
if lit.expressions.is_empty() {
Some(self.ast.ts_string_keyword(SPAN))
} else {
None
}
}
Expression::Identifier(ident) => match ident.name.as_str() {
"undefined" => Some(self.ast.ts_undefined_keyword(SPAN)),
@ -133,12 +138,12 @@ impl<'a> IsolatedDeclarations<'a> {
}
pub fn is_need_to_infer_type_from_expression(expr: &Expression) -> bool {
!matches!(
expr,
match expr {
Expression::NumericLiteral(_)
| Expression::BigintLiteral(_)
| Expression::StringLiteral(_)
| Expression::TemplateLiteral(_)
)
| Expression::BigintLiteral(_)
| Expression::StringLiteral(_) => false,
Expression::TemplateLiteral(lit) => !lit.expressions.is_empty(),
_ => true,
}
}
}

View file

@ -11,6 +11,7 @@ mod diagnostics;
mod r#enum;
mod function;
mod inferrer;
mod literal;
mod module;
mod return_type;
mod scope;

View file

@ -0,0 +1,22 @@
use oxc_allocator::Box;
use oxc_ast::ast::{StringLiteral, TemplateLiteral};
use crate::IsolatedDeclarations;
impl<'a> IsolatedDeclarations<'a> {
pub fn transform_template_to_string(
&self,
lit: &TemplateLiteral<'a>,
) -> Option<Box<'a, StringLiteral<'a>>> {
if lit.expressions.is_empty() {
lit.quasis.first().map(|item| {
self.ast.alloc(self.ast.string_literal(
lit.span,
if let Some(cooked) = &item.value.cooked { cooked } else { &item.value.raw },
))
})
} else {
None
}
}
}

View file

@ -189,25 +189,9 @@ impl<'a> IsolatedDeclarations<'a> {
"undefined" => Some(self.ast.ts_undefined_keyword(ident.span)),
_ => None,
},
Expression::TemplateLiteral(lit) => {
if lit.expressions.is_empty() {
lit.quasis.first().map(|item| {
self.ast.ts_literal_type(
SPAN,
TSLiteral::StringLiteral(self.ast.alloc(self.ast.string_literal(
lit.span,
if let Some(cooked) = &item.value.cooked {
cooked
} else {
&item.value.raw
},
))),
)
})
} else {
None
}
}
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))),
),

View file

@ -0,0 +1,10 @@
export const CSS_VARS_HELPER = `useCssVars`
export function g(func = `useCssVar`) : void {}
export const F = {
a: `a`,
b: [`b`]
} as const
export const BAD = `useCssV${v}ars`

View file

@ -0,0 +1,24 @@
---
source: crates/oxc_isolated_declarations/tests/mod.rs
input_file: crates/oxc_isolated_declarations/tests/fixtures/infer-template-literal.ts
---
==================== .D.TS ====================
export declare const CSS_VARS_HELPER = 'useCssVars';
export declare function g(func?: string): void;
export declare const F: {
readonly a: 'a';
readonly b: readonly ['b'];
};
export declare const BAD: unknown;
==================== Errors ====================
x TS9010: Variable must have an explicit type annotation with
| --isolatedDeclarations.
,-[10:14]
9 |
10 | export const BAD = `useCssV${v}ars`
: ^^^
`----