如何将打字稿定义解析为json?
Posted
技术标签:
【中文标题】如何将打字稿定义解析为json?【英文标题】:How to parse typescript definition to json? 【发布时间】:2017-01-28 01:03:51 【问题描述】:我想把我的typescript定义解析成json,比如
namespace call.common
namespace login
interface Request
userName: string;
password: string;
interface Response
isLogin: boolean
json 可能是这样的:
namespace: "call.common.login",
interfaces: [
"name": "Request",
params: [
name: "userName",
type: "string",
,
name: "password",
type: "string"
]
,
"name": "Response",
params: [
name: "isLogin",
type: boolean
]
]
根据文档Using-the-Compiler-API
我正在尝试使用编译器:
function parseGrpcTypings(fileName, options)
var program = ts.createProgram(fileName, options);
var checker = program.getTypeChecker();
const sourceFile = program.getSourceFiles()[0];
ts.forEachChild(sourceFile, visit);
function visit(node)
if (!isNodeExported(node))
return;
if (node.kind === ts.SyntaxKind.ModuleDeclaration)
ts.forEachChild(node, visit);
else if (node.kind === ts.SyntaxKind.InterfaceDeclaration)
// how to parse interface
else
// how to deal with namespace
function isNodeExported(node)
return (node.flags & ts.NodeFlags.Export) !== 0 || (node.parent && node.parent.kind === ts.SyntaxKind.SourceFile);
parseGrpcTypings("/tmp/test.d.ts",
target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS
);
【问题讨论】:
你希望这个 json 看起来像什么?你想如何解析它?更多信息可能会有用... @NitzanTomer 类似于我发布的内容,但这是一个非常简单的示例 【参考方案1】:根据您的代码,这里有一个 ts2json.js
模块,它将 .d.ts
文件转换为纯 javascript 对象:
const ts = require('typescript');
const PROPERTY_TYPES =
any: ts.SyntaxKind.AnyKeyword,
boolean: ts.SyntaxKind.BooleanKeyword,
number: ts.SyntaxKind.NumberKeyword,
string: ts.SyntaxKind.StringKeyword,
;
class TSNode
constructor(name, type)
this.children = [];
this.addChildren = (name, type) =>
let node = new TSNode(name, type);
this.children.push(node);
return node;
;
this.getType = () => this.type;
this.getObject = () =>
let map = ;
map[this.name] = this.children.length
? this.children
.map(child => child.getObject())
.reduce((pv, child) =>
for (let key in child)
if (pv.hasOwnProperty(key) || key in pv)
Object.assign(pv[key], child[key]);
else
pv[key] = child[key];
return pv;
, )
: this.type;
return map;
;
this.name = name;
this.type = type;
let visit = parent => node =>
switch (node.kind)
case ts.SyntaxKind.ModuleDeclaration:
let moduleName = node.name.text;
ts.forEachChild(node, visit(parent.addChildren(moduleName)));
break;
case ts.SyntaxKind.ModuleBlock:
ts.forEachChild(node, visit(parent));
break;
case ts.SyntaxKind.InterfaceDeclaration:
let interfaceName = node.name.text;
parent[interfaceName] = ;
// console.log('interface');
ts.forEachChild(node, visit(parent.addChildren(interfaceName)));
break;
case ts.SyntaxKind.PropertySignature:
let propertyName = node.name;
let propertyType = node.type;
let arrayDeep = 0;
let realPropertyName =
'string' !== typeof propertyName && 'text' in propertyName
? propertyName.text
: propertyName;
while (propertyType.kind === ts.SyntaxKind.ArrayType)
arrayDeep++;
propertyType = propertyType.elementType;
if (propertyType.kind === ts.SyntaxKind.TypeReference)
let realPropertyType = propertyType.typeName;
parent.addChildren(
realPropertyName,
'Array<'.repeat(arrayDeep) +
(realPropertyType.kind === ts.SyntaxKind.QualifiedName
? realPropertyType.getText()
: 'text' in realPropertyType
? realPropertyType.text
: realPropertyType) +
'>'.repeat(arrayDeep)
);
else
for (let type in PROPERTY_TYPES)
if (propertyType.kind === PROPERTY_TYPES[type])
parent.addChildren(realPropertyName, type);
break;
break;
default:
;
module.exports = function(filename, options)
const ROOT_NAME = 'root';
const node = new TSNode(ROOT_NAME);
let program = ts.createProgram([filename], options);
let checker = program.getTypeChecker();
let sourceFile = program.getSourceFiles()[1];
ts.forEachChild(sourceFile, visit(node));
return node.getObject()[ROOT_NAME];
;
您可以使用JSON.stringify
方法获取JSON 字符串。
以下 TypeScript 定义文件eg.d.ts
:
declare namespace School.Users
interface User
lastName: string;
firstName: string;
email: string;
interface Student extends User
graduation: number;
mainTeacher: Teacher;
interface Teacher extends User
classes: Student[][];
room: School.Building.Room;
declare namespace School.Building
interface Room
name: string;
可以通过以下方式解析为 JSON:
node -e "console.log(JSON.stringify(require('./ts2json.js')('./eg.d.ts', ), null, '\t'))"
输出:
"School":
"Users":
"User":
"lastName": "string",
"firstName": "string",
"email": "string"
,
"Student":
"graduation": "number",
"mainTeacher": "Teacher"
,
"Teacher":
"classes": "Array<Array<Student>>",
"room": "School.Building.Room"
,
"Building":
"Room":
"name": "string"
【讨论】:
不适用于typescript/lib/lib.dom.d.ts
- 结果未定义【参考方案2】:
MrMaxie/ts-types-parser 可以从*.d.ts
文件中解析单一类型
const TSTypesParser = require('ts-types-parser');
const parser = new TSTypesParser();
// input file
parser.setSource('node_modules/typescript/lib/lib.dom.d.ts');
parser.setTarget('lib.dom.d.ts.js'); // required, will create empty file
// entry point
const mainType = 'CanvasRenderingContext2D';
parser.mainType(mainType);
const result = [];
parser.on('level-up', levelData =>
const fullPath = `$mainType.$levelData.path.join('.')`;
const r = `$fullPath /*: $levelData.type */`;
result.push(r);
);
parser.on('done', () =>
// restore output
console.log = console._log;
console.warn = console._warn;
console.log(result.join('\n'));
)
// disable output from parser.run
console._log = console.log;
console._warn = console.warn;
console.log = () => ;
console.warn = () => ;
parser.run();
【讨论】:
以上是关于如何将打字稿定义解析为json?的主要内容,如果未能解决你的问题,请参考以下文章