mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
feat(isolated-declarations): improve the inference template literal (#3797)
This commit is contained in:
parent
b0d7355c98
commit
a37138f1ec
7 changed files with 79 additions and 28 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ mod diagnostics;
|
|||
mod r#enum;
|
||||
mod function;
|
||||
mod inferrer;
|
||||
mod literal;
|
||||
mod module;
|
||||
mod return_type;
|
||||
mod scope;
|
||||
|
|
|
|||
22
crates/oxc_isolated_declarations/src/literal.rs
Normal file
22
crates/oxc_isolated_declarations/src/literal.rs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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))),
|
||||
),
|
||||
|
|
|
|||
10
crates/oxc_isolated_declarations/tests/fixtures/infer-template-literal.ts
vendored
Normal file
10
crates/oxc_isolated_declarations/tests/fixtures/infer-template-literal.ts
vendored
Normal 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`
|
||||
|
|
@ -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`
|
||||
: ^^^
|
||||
`----
|
||||
Loading…
Reference in a new issue