简体   繁体   English

节点读取ts模块/读取代码文件

[英]Node read ts module / read code file

How do you read the classes from a file?你如何从文件中读取类?

.src/my-a.service.ts .src/my-a.service.ts

export class MyAService {
    ...
}

.src/my-b.service.ts .src/my-b.service.ts

export class MyBService {
    ...
}

./read-modules.js ./read-modules.js

const fs = require('fs');
const _ = require('lodash');

let files = fs.readdirSync('./src')
    .filter(item => {
        return _.includes(item, '.service.ts')
    });


files.forEach(item => {
    // get ['MyAService', 'MyBService']
});

I know you could do some string parsing but is there a high level way to read js/ts exports from a file(not import the code but just get the names of the exported classes).我知道您可以进行一些字符串解析,但是有没有一种高级方法可以从文件中读取 js/ts 导出(不是导入代码,而是获取导出类的名称)。

Edit 1: There is X number of *.service.ts files my-a.service.ts and my-b.service.ts are just examples.编辑 1:有 X 个 *.service.ts 文件my-a.service.tsmy-b.service.ts只是示例。 I'm not trying to import or require these classes to use them in code just get the class names for code generation.我不是试图导入或要求这些类在代码中使用它们,只是获取用于代码生成的类名。

Edit 2: I looks like tsreflect-compiler is what I need:编辑 2:我看起来像tsreflect-compiler是我需要的:

const fs = require('fs');
const _ = require('lodash');
const compiler = require('tsreflect-compiler');

let files = fs.readdirSync('./src')
    .filter(item => {
        return _.includes(item, '.service.ts')
    });


let mods = new Map();
files.forEach(item => {
    let diag = compiler.compile(
        [`./src/${item}`],
        {
            noLib: false,
            suppressImplicitAnyIndexErrors: true,
            noImplicitAny: false,
            module: 'ES2015',
            moduleResolution: 'Node',
            target: 'ES5'
        },
        {
            readFile: (filename, onError) => {
                let text;
                try {
                    text = fs.readFileSync(filename, 'utf8');
                } catch (error) {
                    if (onError) {
                        onError(e.message);
                    }
                    text = '';
                }
                return text;
            },
            writeFile: (fileName, data, writeByteOrderMark, onError) => {
                mods.set(item, JSON.parse(data).declares.map(d => d.name));
            }
        }
    );
});

mods.forEach((value, key) => {
    console.log(key); // my-a.service.ts
    console.dir(value); // [ 'MyAService' ]
});

However tsreflect-compiler only uses TypeScript 1.4 compiler and I need 2.x newer.然而tsreflect-compiler只使用 TypeScript 1.4 编译器,我需要 2.x 更新。 Is there a more modern solution?有没有更现代的解决方案?

This ended up being my solution:这最终成为我的解决方案:

const fs = require('fs');
const _ = require('lodash');
const ts = require('typescript');

let files = fs.readdirSync('./src')
    .filter(item => _.includes(item, '.service.ts'));

let mods = new Map();
files.forEach(file => {
    let ex = [];
    // https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#using-the-type-checker
    // Build a program using the set of root file names in fileNames
    let program = ts.createProgram(
        [`./src/${file}`],
        {
            module: ts.ModuleKind.ES2015,
            moduleResolution: ts.ModuleResolutionKind.NodeJs,
            target: ts.ScriptTarget.ES5
        }
    );
    // Get the checker, we will use it to find more about classes
    let checker = program.getTypeChecker();
    // Visit every sourceFile in the program
    program.getSourceFiles()
        .filter(sourceFile => _.includes(sourceFile.fileName, file))
        .forEach(sourceFile => {
            // Walk the tree to search for classes
            ts.forEachChild(sourceFile, node => {
                if (node.kind === ts.SyntaxKind.ClassDeclaration) {
                    // This is a top level class, get its symbol
                    let symbol = checker.getSymbolAtLocation(node.name);
                    ex.push(symbol.getName());
                }
            });
        });
    mods.set(file, ex);
});

mods.forEach((value, key) => {
    console.log(key); // my-a.service.ts
    console.dir(value); // [ 'MyAService' ]
});

Not sure what you're use case is but the easiest way would be -不确定你的用例是什么,但最简单的方法是 -

const serviceA = require('./MyAService');
const keys = Object.keys(serviceA);

If not, you'd have to read in the file with fs and then do some string matching/regex to find all of the exported function which could be very tricky.如果没有,你必须用fs读入文件,然后做一些字符串匹配/正则表达式来找到所有导出的函数,这可能非常棘手。

Since Javascript/ES6 doesn't actually have classes, you shouldn't be relying on class names.由于 Javascript/ES6 实际上没有类,因此您不应该依赖类名。

What you are looking for is named exports:您正在寻找的是命名导出:

exports.MyBService = class MyBService {
    ...
}

That way you can do这样你就可以做到

const allServices = require('./myservices')
console.log(Object.keys(allServices))

In node.js, you would export files using the commonjs format for javascript files.在 node.js 中,您将使用 commonjs 格式为 javascript 文件导出文件。

Basic Example for js js 的基本示例

const someModule = require('./someModule');

const methods = param => { return param; };

modules.exports = { methods }

Typescript gets to use the new es6 format, but you need to setup your typescript compiler for it to work with node. Typescript 可以使用新的 es6 格式,但是您需要设置您的 typescript 编译器以使其与 node.js 一起使用。

import someClass from './someClass';
someClass.method();
export class name { .. }

use typescript-require To get ts file object in js 使用typescript-require在js中获取ts文件对象

https://www.npmjs.com/package/typescript-require https://www.npmjs.com/package/typescript-require

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM