在tsc编译期间如何在JSX组件中添加额外的道具

问题描述

我在我的TypeScript node.js项目中使用JSX语法(根本不使用React)。

在我的tsconfig中,我正在使用自己的jsxFactory

{
  "compilerOptions": {
    ...
    "jsxFactory": "myJSXFactory",...
  }
}
<MyBanner backgroundColor="red" />

一切正常,并且在tsc编译后,上面的JSX变为了

myJSXFactory(MyBanner,{
  backgroundColor: 'red' 
});

现在,我想在编译期间向props的JSX组件添加额外的All,例如:

myJSXFactory(MyBanner,{
  backgroundColor: 'red',theme: myTheme // a variable that's available in the parent context
});

我当时在看Compiler API,但是在JSX转换过程中如何修改代码尚不清楚。

解决方法

正在回答我自己的问题...

import * as ts from "typescript";

type TYPESCRIPT = typeof ts;
function nodeVisitor(ts: TYPESCRIPT,ctx: ts.TransformationContext,sf: ts.SourceFile) {
  const visitor: ts.Visitor = (node) => {
      if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
          // Create theme attr
          const themeAttr = ts.createPropertyAssignment(
              'theme',ts.createIdentifier('request.query.theme')
          )

          // Create __my_extra_prop={{ theme: request.query.theme }} JSX Attribute
          const sourceJsxAttr = ts.createJsxAttribute(
              ts.createIdentifier('__my_extra_prop'),ts.createJsxExpression(undefined,ts.createObjectLiteral([themeAttr]))
          )
          const jsxAttributes = ts.createJsxAttributes([...node.attributes.properties,sourceJsxAttr])
          const clonedNode = ts.getMutableClone(node)
          clonedNode.attributes = jsxAttributes
          return clonedNode
      }
      return ts.visitEachChild(node,visitor,ctx)
  }
  return visitor
}

function transform(ts: TYPESCRIPT): ts.TransformerFactory<ts.SourceFile> {
  return (ctx) => (sf) => ts.visitNode(sf,nodeVisitor(ts,ctx,sf))
}

// JSX expression
const source = "<MyBanner backgroundColor='red' />";

const result = ts.transpileModule(source,{
    compilerOptions: {
      module: ts.ModuleKind.CommonJS,jsxFactory: "myJSXFactory",jsx: ts.JsxEmit.React
    },transformers: {
      before: [transform(ts)]
    }
  }
);

console.log(result.outputText);

https://repl.it/@ABMAdnan/TS-JSX-extra-props#index.ts

myJSXFactory(MyBanner,{ backgroundColor: 'red',__my_extra_prop: { theme: request.query.theme } });