diff --git a/crates/oxc_isolated_declarations/src/types.rs b/crates/oxc_isolated_declarations/src/types.rs index 7402629ac34ba..dd95697882560 100644 --- a/crates/oxc_isolated_declarations/src/types.rs +++ b/crates/oxc_isolated_declarations/src/types.rs @@ -8,7 +8,7 @@ use oxc_ast::{ }, }; use oxc_span::{ContentEq, GetSpan, SPAN, Span}; -use oxc_syntax::number::ToJsString; +use oxc_syntax::identifier::is_identifier_name; use crate::{ IsolatedDeclarations, @@ -69,19 +69,18 @@ impl<'a> IsolatedDeclarations<'a> { /// Convert a a computed property key to a static property key when possible fn transform_property_key(&self, key: &PropertyKey<'a>) -> PropertyKey<'a> { match key { - // [100] -> 100 - PropertyKey::NumericLiteral(literal) => self.ast.property_key_static_identifier( - literal.span, - self.ast.atom(&literal.value.to_js_string()), - ), - // `["string"] -> string` - PropertyKey::StringLiteral(literal) => { + // ["string"] -> string + PropertyKey::StringLiteral(literal) if is_identifier_name(&literal.value) => { self.ast.property_key_static_identifier(literal.span, literal.value.as_str()) } - // `[`string`] -> string - PropertyKey::TemplateLiteral(literal) => { + // [`string`] -> string + PropertyKey::TemplateLiteral(literal) + if is_identifier_name(&literal.quasis[0].value.raw) => + { self.ast.property_key_static_identifier(literal.span, literal.quasis[0].value.raw) } + // [100] -> 100 + // number literal will be cloned as-is _ => key.clone_in(self.ast.allocator), } } @@ -136,7 +135,9 @@ impl<'a> IsolatedDeclarations<'a> { } let params = self.transform_formal_parameters(&function.params); let key = self.transform_property_key(key); - let computed = key.is_expression(); + let computed = key + .as_expression() + .is_some_and(|k| !k.is_string_literal() && !k.is_number_literal()); return Some(self.ast.ts_signature_method_signature( object.span, @@ -214,7 +215,8 @@ impl<'a> IsolatedDeclarations<'a> { let key = self.transform_property_key(key); let property_signature = self.ast.ts_signature_property_signature( object.span, - key.is_expression(), + key.as_expression() + .is_some_and(|k| !k.is_string_literal() && !k.is_number_literal()), false, is_const, key, diff --git a/crates/oxc_isolated_declarations/tests/fixtures/object.ts b/crates/oxc_isolated_declarations/tests/fixtures/object.ts index 6e13542f4c834..e33a158792b1f 100644 --- a/crates/oxc_isolated_declarations/tests/fixtures/object.ts +++ b/crates/oxc_isolated_declarations/tests/fixtures/object.ts @@ -53,3 +53,48 @@ const ObjectKeys = { [-3]: 4, [4n]: 5, }; + +type family = + '-apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif' +const family: family = + '-apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif' +const theme = { + 'font-family': family as family +} as const + +const X = { + 'async': 1, + 'await': 2, +} + +const Y = { + 0: 0, + [1]: 1, + ["2"]: 2, + set 3(v: number) {}, + set [4](v: number) {}, + set ["5"](v: number) {}, +}; + + +const exoticKeys = { + // --- WORKING KEYS --- + "a": "latin", // latin + "é": "latin-1 supplement", // latin-1 supplement + "ø": "extended latin", // extended latin + "Ж": "cyrillic", // cyrillic + "你": "chinese", // chinese + "あ": "japanese", // japanese + "한": "korean", // korean + "a\u0301": "zalgo/combining", // zalgo (a + combining acute accent) + + // --- NON-WORKING KEYS --- + "😃": "emoji", // emoji + "👍🏻": "emoji with skin tone", // emoji + skin tone + "👨‍👩‍👧‍👦": "emoji sequence", // emoji sequence (family) + "±": "math symbol", // math symbol + "€": "currency", // currency + "“": "curly quote", // curly quote + "\u0000": "null byte", // null byte (not expected to work) + "\\": "backslash", // backslash (unique error) +}; diff --git a/crates/oxc_isolated_declarations/tests/snapshots/object.snap b/crates/oxc_isolated_declarations/tests/snapshots/object.snap index a6dee2af2c297..0c09662c92449 100644 --- a/crates/oxc_isolated_declarations/tests/snapshots/object.snap +++ b/crates/oxc_isolated_declarations/tests/snapshots/object.snap @@ -30,6 +30,43 @@ declare const ObjectKeys: { 3: number [-3]: number }; +type family = "-apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif"; +declare const family: family; +declare const theme: { + readonly "font-family": family +}; +declare const X: { + async: number + await: number +}; +declare const Y: { + 0: number + 1: number + "2": number + 3: number + 4: number + "5": number +}; +declare const exoticKeys: { + // --- WORKING KEYS --- + a: string + é: string + ø: string + Ж: string + 你: string + あ: string + 한: string + á: string + // --- NON-WORKING KEYS --- + "😃": string + "👍🏻": string + "👨‍👩‍👧‍👦": string + "±": string + "€": string + "“": string + "\0": string + "\\": string +}; ==================== Errors ==================== diff --git a/tasks/coverage/snapshots/transpile.snap b/tasks/coverage/snapshots/transpile.snap index 7670a33a6a576..711a6e15f899f 100644 --- a/tasks/coverage/snapshots/transpile.snap +++ b/tasks/coverage/snapshots/transpile.snap @@ -106,7 +106,7 @@ export declare const D: { [Symbol.iterator]: number [globalThis.Symbol.toStringTag]: number 1: number - 2: number + "2": number }; export {};