Skip to content

Commit 43e7724

Browse files
committed
refactor: improve TypeScript types and add JSXIdentifier guard
- Remove eslint-disable comments for unsafe types - Add type guard to ensure JSXAttribute name is JSXIdentifier - Remove explicit type annotations from visitor methods - Improve type safety throughout JSXAttribute visitor
1 parent 35610e4 commit 43e7724

1 file changed

Lines changed: 23 additions & 35 deletions

File tree

src/babel/plugin.ts

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
/* eslint-disable @typescript-eslint/no-unsafe-argument */
2-
/* eslint-disable @typescript-eslint/no-unsafe-call */
3-
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
4-
/* eslint-disable @typescript-eslint/no-explicit-any */
5-
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
6-
71
/**
82
* Babel plugin for react-native-tailwind
93
* Transforms className props to style props at compile time
@@ -29,6 +23,7 @@ import { createStyleFunction, processStaticClassNameWithModifiers } from "./util
2923
import { addStyleSheetImport, injectStylesAtTop } from "./utils/styleInjection.js";
3024
import {
3125
addOrMergePlaceholderTextColorProp,
26+
findStyleAttribute,
3227
mergeDynamicStyleAttribute,
3328
mergeStyleAttribute,
3429
mergeStyleFunctionAttribute,
@@ -128,13 +123,13 @@ export default function reactNativeTailwindBabelPlugin(
128123
},
129124

130125
// Check if StyleSheet is already imported and track tw/twStyle imports
131-
ImportDeclaration(path: NodePath, state: PluginState) {
132-
const node = path.node as any;
126+
ImportDeclaration(path, state) {
127+
const node = path.node;
133128

134129
// Track react-native StyleSheet import
135130
if (node.source.value === "react-native") {
136131
const specifiers = node.specifiers;
137-
const hasStyleSheet = specifiers.some((spec: any) => {
132+
const hasStyleSheet = specifiers.some((spec) => {
138133
if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
139134
return spec.imported.name === "StyleSheet";
140135
}
@@ -153,7 +148,7 @@ export default function reactNativeTailwindBabelPlugin(
153148
// Track tw/twStyle imports from main package (for compile-time transformation)
154149
if (node.source.value === "@mgcrea/react-native-tailwind") {
155150
const specifiers = node.specifiers;
156-
specifiers.forEach((spec: any) => {
151+
specifiers.forEach((spec) => {
157152
if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
158153
const importedName = spec.imported.name;
159154
if (importedName === "tw" || importedName === "twStyle") {
@@ -168,8 +163,8 @@ export default function reactNativeTailwindBabelPlugin(
168163
},
169164

170165
// Handle tw`...` tagged template expressions
171-
TaggedTemplateExpression(path: NodePath, state: PluginState) {
172-
const node = path.node as any;
166+
TaggedTemplateExpression(path, state) {
167+
const node = path.node;
173168

174169
// Check if the tag is a tracked tw import
175170
if (!t.isIdentifier(node.tag)) {
@@ -215,8 +210,8 @@ export default function reactNativeTailwindBabelPlugin(
215210
},
216211

217212
// Handle twStyle('...') call expressions
218-
CallExpression(path: NodePath, state: PluginState) {
219-
const node = path.node as any;
213+
CallExpression(path, state) {
214+
const node = path.node;
220215

221216
// Check if the callee is a tracked twStyle import
222217
if (!t.isIdentifier(node.callee)) {
@@ -264,8 +259,14 @@ export default function reactNativeTailwindBabelPlugin(
264259
processTwCall(className, path, state, parseClassName, generateStyleKey, splitModifierClasses, t);
265260
},
266261

267-
JSXAttribute(path: NodePath, state: PluginState) {
268-
const node = path.node as any;
262+
JSXAttribute(path, state) {
263+
const node = path.node;
264+
265+
// Ensure we have a JSXIdentifier name (not JSXNamespacedName)
266+
if (!t.isJSXIdentifier(node.name)) {
267+
return;
268+
}
269+
269270
const attributeName = node.name.name;
270271

271272
// Only process configured className-like attributes
@@ -300,7 +301,7 @@ export default function reactNativeTailwindBabelPlugin(
300301
// Handle placeholder modifiers first (they generate placeholderTextColor prop, not style)
301302
if (placeholderModifiers.length > 0) {
302303
// Check if this is a TextInput component (placeholder only works on TextInput)
303-
const jsxOpeningElement = path.parent;
304+
const jsxOpeningElement = path.parent as BabelTypes.JSXOpeningElement;
304305
const componentSupport = getComponentModifierSupport(jsxOpeningElement, t);
305306

306307
if (componentSupport?.supportedModifiers.includes("placeholder")) {
@@ -309,8 +310,7 @@ export default function reactNativeTailwindBabelPlugin(
309310

310311
if (placeholderColor) {
311312
// Add or merge placeholderTextColor prop
312-
const parent = path.parent as any;
313-
addOrMergePlaceholderTextColorProp(parent, placeholderColor, t);
313+
addOrMergePlaceholderTextColorProp(jsxOpeningElement, placeholderColor, t);
314314
}
315315
} else {
316316
// Warn if placeholder modifier used on non-TextInput element
@@ -370,10 +370,7 @@ export default function reactNativeTailwindBabelPlugin(
370370
const modifierTypes = Array.from(new Set(supportedModifierClasses.map((m) => m.modifier)));
371371
const styleFunctionExpression = createStyleFunction(styleExpression, modifierTypes, t);
372372

373-
const parent = path.parent as any;
374-
const styleAttribute = parent.attributes.find(
375-
(attr: any) => t.isJSXAttribute(attr) && attr.name.name === targetStyleProp,
376-
);
373+
const styleAttribute = findStyleAttribute(path, targetStyleProp, t);
377374

378375
if (styleAttribute) {
379376
mergeStyleFunctionAttribute(path, styleAttribute, styleFunctionExpression, t);
@@ -395,10 +392,7 @@ export default function reactNativeTailwindBabelPlugin(
395392
const modifierTypes = usedModifiers;
396393
const styleFunctionExpression = createStyleFunction(styleExpression, modifierTypes, t);
397394

398-
const parent = path.parent as any;
399-
const styleAttribute = parent.attributes.find(
400-
(attr: any) => t.isJSXAttribute(attr) && attr.name.name === targetStyleProp,
401-
);
395+
const styleAttribute = findStyleAttribute(path, targetStyleProp, t);
402396

403397
if (styleAttribute) {
404398
mergeStyleFunctionAttribute(path, styleAttribute, styleFunctionExpression, t);
@@ -433,10 +427,7 @@ export default function reactNativeTailwindBabelPlugin(
433427
state.styleRegistry.set(styleKey, styleObject);
434428

435429
// Check if there's already a style prop on this element
436-
const parent = path.parent as any;
437-
const styleAttribute = parent.attributes.find(
438-
(attr: any) => t.isJSXAttribute(attr) && attr.name.name === targetStyleProp,
439-
);
430+
const styleAttribute = findStyleAttribute(path, targetStyleProp, t);
440431

441432
if (styleAttribute) {
442433
// Merge with existing style prop
@@ -465,10 +456,7 @@ export default function reactNativeTailwindBabelPlugin(
465456
state.hasClassNames = true;
466457

467458
// Check if there's already a style prop on this element
468-
const parent = path.parent as any;
469-
const styleAttribute = parent.attributes.find(
470-
(attr: any) => t.isJSXAttribute(attr) && attr.name.name === targetStyleProp,
471-
);
459+
const styleAttribute = findStyleAttribute(path, targetStyleProp, t);
472460

473461
if (styleAttribute) {
474462
// Merge with existing style prop

0 commit comments

Comments
 (0)