#typescript #jsx #tsc
#typescript #jsx #tsc
Вопрос:
Я использую синтаксис JSX в своем TypeScript node.js проект (без использования React вообще).
В моем tsconfig
я использую свой собственный jsxFactory
{
"compilerOptions": {
...
"jsxFactory": "myJSXFactory",
...
}
}
<MyBanner backgroundColor="red" />
Все работает нормально, и вышеупомянутый JSX становится таким после компиляции tsc
myJSXFactory(MyBanner, {
backgroundColor: 'red'
});
Теперь я хочу добавить дополнительные props
к All
компонентам JSX во время компиляции, например:
myJSXFactory(MyBanner, {
backgroundColor: 'red',
theme: myTheme // a variable that's available in the parent context
});
Я просматривал API компилятора, но неясно, как изменить исходный код во время преобразования JSX.
Ответ №1:
Отвечая на мой собственный вопрос…
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 } });