【问题标题】:In an angular app, can TSLint enforce module imports via path mapping iso via relative paths?在 Angular 应用程序中,TSLint 可以通过路径映射 iso 通过相对路径强制导入模块吗?
【发布时间】:2019-06-12 21:09:32
【问题描述】:

假设我对 Angular 项目有以下设置:

apps/my-app
libs/my-comp/my-lib

在 my-app 代码中,我使用来自 my-lib 的代码。我可以通过 typescript 导入导入 my-lib 代码,例如import ../../libs/my-comp/my-lib,但这很丑陋且容易出错。使用path mapping,我可以模拟模块导入,例如import { MyLibModule} from @my-comp/my-lib。干净多了。

但是,我们可以强制执行吗?我们如何防止开发人员使用相对路径从另一个模块导入代码?对此有 TSLint 规则吗?我们应该编写自定义 TSLint 代码吗?有人已经尝试过这样做:)?

【问题讨论】:

    标签: angular typescript tslint


    【解决方案1】:

    我们有类似的设置,我们实现了 2 个自定义 lint 规则:

    • 禁止从my-lib 进行相对导入
    • 禁止从库本身内部的@my-comp/my-lib 导入

    也许更好的设置是使用nx-workspace(参见预建约束部分)。它具有类似的规则并增加了更多:

    • Libs 无法导入应用程序。
    • 通过 loadChildren 加载库的项目也不能使用 ESM 导入来导入它。
    • 不允许循环依赖。
    • 无法使用相对导入来导入库。

    这是我们禁止从库中相对导入的规则的实现。它有效,但可能存在一些我们尚未发现的严重问题(例如减慢 lint :)

    import * as ts from 'typescript';
    import * as Lint from 'tslint';
    
    export class Rule extends Lint.Rules.AbstractRule {
        static readonly FAILURE_STRING = `Import should be from '${Rule.SHARED_IMPORT}'`;
        static readonly SHARED_IMPORT = 'my-lib';
    
        public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
            return this.applyWithFunction(sourceFile, walk);
        }
    }
    
    function walk(ctx: Lint.WalkContext<void>) {
        return ts.forEachChild(ctx.sourceFile, cb);
    
        function cb(node: ts.Node): void {
            if (node.kind !== ts.SyntaxKind.ImportDeclaration) {
                return;
            }
    
            const importLocation = getImportLocation(node.getText());
    
            if (containsIncorrectImportFromSharedFolder(importLocation)) {
                const locationWidth = importLocation.length + 3;
                const fix = new Lint.Replacement(node.getEnd() - locationWidth, locationWidth, `'${Rule.SHARED_IMPORT}';`);
                return ctx.addFailureAtNode(node, Rule.FAILURE_STRING, fix);
            }
    
            return ts.forEachChild(node, cb);
        }
    
        function containsIncorrectImportFromSharedFolder(importLocation: String): boolean {
            return importLocation.indexOf(Rule.SHARED_IMPORT) > -1 && importLocation !== Rule.SHARED_IMPORT;
        }
    
        function getImportLocation(location: string): string {
            const importLocation = location.match(/'(.*?[^'])'/);
            return importLocation !== null ? importLocation[1] : '';
        }
    }
    
    

    您必须使用tsc 将规则编译为js

    node "node_modules/typescript/bin/tsc" tools/tslint-rules/myLibImportRule.ts
    

    你必须把它添加到tslint.json:

    "rulesDirectory": [
        ...
        "tools/tslint-rules",
        ...
    ],
    "rules": {
        ...,
        "my-lib-import": true,
        ...
    }
    

    规则名称是文件的名称myLibImportRule.js => my-lib-import

    【讨论】:

    • 感谢您的回答。是的,我听说过 NX,可能这确实是要走的路。但我首先尝试了解仅使用 CLI 和 tslint 的可行性。
    • 你能指出正确的方向吗?如何编写这样一个禁止从另一个模块进行相对导入的自定义规则?
    • @DavidBulté 我添加了我们的自定义规则作为示例
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-08
    • 2010-09-21
    相关资源
    最近更新 更多