Skip to content

Commit 032cd40

Browse files
Brooooooklynclaude
andcommitted
fix: handle computed keys in array, tuple, generic, and parenthesized types
The computed property key collector only handled TSTypeLiteral, TSUnionType, and TSIntersectionType. Added support for TSArrayType, TSTupleType, TSTypeReference (generics), and TSParenthesizedType so computed keys like `[myKey]` inside these type structures are correctly preserved. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 16254f5 commit 032cd40

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

crates/oxc_angular_compiler/src/component/import_elision.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,24 @@ impl<'a> ImportElisionAnalyzer<'a> {
224224
Self::collect_computed_keys_from_ts_type(ty, result);
225225
}
226226
}
227+
TSType::TSArrayType(array_type) => {
228+
Self::collect_computed_keys_from_ts_type(&array_type.element_type, result);
229+
}
230+
TSType::TSTupleType(tuple_type) => {
231+
for element in &tuple_type.element_types {
232+
Self::collect_computed_keys_from_ts_type(element.to_ts_type(), result);
233+
}
234+
}
235+
TSType::TSTypeReference(type_ref) => {
236+
if let Some(type_args) = &type_ref.type_arguments {
237+
for ty in &type_args.params {
238+
Self::collect_computed_keys_from_ts_type(ty, result);
239+
}
240+
}
241+
}
242+
TSType::TSParenthesizedType(paren_type) => {
243+
Self::collect_computed_keys_from_ts_type(&paren_type.type_annotation, result);
244+
}
227245
_ => {}
228246
}
229247
}
@@ -1769,4 +1787,80 @@ class MyComponent {
17691787
"myKey in type literal nested within union should be preserved"
17701788
);
17711789
}
1790+
1791+
#[test]
1792+
fn test_computed_key_in_array_type_preserved() {
1793+
// Review claim: TSArrayType `{ [key]: string }[]` is not handled
1794+
let source = r#"
1795+
import { Component, Input } from '@angular/core';
1796+
import { myKey } from './keys';
1797+
1798+
@Component({ selector: 'test' })
1799+
class MyComponent {
1800+
@Input() items: { [myKey]: string }[];
1801+
}
1802+
"#;
1803+
let type_only = analyze_source(source);
1804+
assert!(
1805+
!type_only.contains("myKey"),
1806+
"myKey in array element type literal should be preserved"
1807+
);
1808+
}
1809+
1810+
#[test]
1811+
fn test_computed_key_in_generic_type_arg_preserved() {
1812+
// Review claim: TSTypeReference `Array<{ [key]: string }>` is not handled
1813+
let source = r#"
1814+
import { Component, Input } from '@angular/core';
1815+
import { myKey } from './keys';
1816+
1817+
@Component({ selector: 'test' })
1818+
class MyComponent {
1819+
@Input() items: Array<{ [myKey]: string }>;
1820+
}
1821+
"#;
1822+
let type_only = analyze_source(source);
1823+
assert!(
1824+
!type_only.contains("myKey"),
1825+
"myKey in generic type argument type literal should be preserved"
1826+
);
1827+
}
1828+
1829+
#[test]
1830+
fn test_computed_key_in_tuple_type_preserved() {
1831+
// Review claim: TSTupleType is not handled
1832+
let source = r#"
1833+
import { Component, Input } from '@angular/core';
1834+
import { myKey } from './keys';
1835+
1836+
@Component({ selector: 'test' })
1837+
class MyComponent {
1838+
@Input() pair: [string, { [myKey]: number }];
1839+
}
1840+
"#;
1841+
let type_only = analyze_source(source);
1842+
assert!(
1843+
!type_only.contains("myKey"),
1844+
"myKey in tuple element type literal should be preserved"
1845+
);
1846+
}
1847+
1848+
#[test]
1849+
fn test_computed_key_in_parenthesized_type_preserved() {
1850+
// Review claim: TSParenthesizedType is not handled
1851+
let source = r#"
1852+
import { Component, Input } from '@angular/core';
1853+
import { myKey } from './keys';
1854+
1855+
@Component({ selector: 'test' })
1856+
class MyComponent {
1857+
@Input() data: ({ [myKey]: string });
1858+
}
1859+
"#;
1860+
let type_only = analyze_source(source);
1861+
assert!(
1862+
!type_only.contains("myKey"),
1863+
"myKey in parenthesized type literal should be preserved"
1864+
);
1865+
}
17721866
}

0 commit comments

Comments
 (0)