javascript - 打字稿源解析:获取与某些反应类相关的接口
问题描述
我想从与此类相关的接口中声明的 React 类获取道具。例如我有这种代码
interface SomeProps {
text: string;
label?: string;
}
class SomeClass extends React.Component<SomeProps> {
...
}
如何使用源文件中的 ts 编译器 api 获取在 SomeProps 中声明的 SomeClass 的道具?
解决方案
当然,您可以使用编译器 API 来实现这一点。
// sample.ts
import * as React from 'react'
interface SomeProps {
text: string;
label?: string;
}
class SomeClass extends React.Component<SomeProps> {
}
// getProps.ts
import * as ts from "typescript";
function isReactComponent (baseType: ts.Type) {
if (baseType == null) return false;
let baseTypeSymbol = baseType.getSymbol();
if (baseTypeSymbol == null) return false;
// Base type is named Component
if (baseTypeSymbol.getName() !== "Component") return false;
var declarations = baseTypeSymbol.declarations;
if (declarations == null) return false;
// With the declartion beeing located inside the react module
return declarations.some(r => r.getSourceFile().fileName.indexOf("node_modules/@types/react") !== -1);
}
function compile(fileNames: string[], options: ts.CompilerOptions): void {
let program = ts.createProgram(fileNames, options);
let sample = program.getSourceFile("sample.ts");
if (sample == null) return;
let checker = program.getTypeChecker();
// Get declarations inside the file
let list = sample.getChildAt(0) as ts.SyntaxList;
for (let i = 0, n = list.getChildCount(); i < n; i++) {
let clazz = list.getChildAt(i);
// if the child is a class
if (!ts.isClassDeclaration(clazz)) continue;
// Get the heritage classes of the class
let heritageClauses = clazz.heritageClauses;
if (heritageClauses == null) continue;
// Iterate the heritage clauses
for (const heritageClause of heritageClauses) {
// Only take the extends clauses
if (heritageClause.token !== ts.SyntaxKind.ExtendsKeyword) continue;
// Get the type of the extends
let extendsType = heritageClause.types[0];
// If the base type is React.Component
if (isReactComponent(checker.getTypeFromTypeNode(extendsType))) {
// Get the type argument of the expression
var propType = extendsType.typeArguments![0];
let type = checker.getTypeFromTypeNode(propType);
console.log(`The name of props is ${type.getSymbol()!.getName()}`);
var props = type.getProperties();
for (let prop of props) {
console.log(` Contains prop: ${prop.getName()}`);
}
}
}
}
}
compile(["sample.ts"], {});
推荐阅读
- openssl - 如何使用 OpenSSL 为 X509 证书生成所有权证明?
- java - Shiro - redirect to login page after session timeout
- scala - Scala:如何从嵌套类中引用类属性
- powerbi - 更改数据集以支持有效身份
- ios - Swift:创建 TCP 侦听器
- google-maps - 谷歌地图上的 Openseamap Gebco 深度层 Wms 错误
- facebook - 我是否需要制作应用程序以使用 API 访问公共 Facebook 信息以供个人使用?
- java - 无法在我的 Android Studio 文件中合并 dex 错误
- python - 根据条件从另一个列表创建一个新列表
- c++ - 将单个 C++ 程序分解为具有继承的多文件程序