有什么方法可以在文件中运行代码而无需将它们导入TypeScript(Angular项目)中?也许通过在tsconfig中通过一些配置指定文件模式?
我想做的是将一些类注册到一个全局对象中,但是我不想在一个文件中维护类列表。我宁愿在每个类定义下使用简单的代码行,如下所示:
export class MyClassToRegister {...}
GlobalRegistry.register(MyClassToRegister);
我知道在导入文件时将执行此代码,但是有时为时已晚。关于如何实现这一目标?
答案 0 :(得分:1)
一种解决方案是使用multi-file namespaces,该代码允许将代码拆分为多个文件,而不必导入modules。
以下是TypeScript documentation on namespaces中的一个简化示例。
Validation.ts文件
namespace Validation {
export interface StringValidator {
isAcceptable(s: string): boolean;
}
}
LettersOnlyValidator.ts文件
namespace Validation {
const lettersRegexp = /^[A-Za-z]+$/;
export class LettersOnlyValidator implements StringValidator {
isAcceptable(s: string) {
return lettersRegexp.test(s);
}
}
}
答案 1 :(得分:1)
是的,通过使用Webpack的require.context(...)
,您可以将文件目录导入到包中。
快速说明:您仍将文件导入捆绑包中,但是,如果添加/删除文件,则不必静态定义每个导入路径,也不必手动保持它们最新。
让我们使用以下示例文件结构:
src/
items/
item1.ts
item2.ts
item3.ts
registry.ts
index.ts
这是我们从目录中需要的项目:
//item1.ts, item2.ts, item3.ts
import GlobalRegistry from "../registry";
export class Item1 {
//...
}
GlobalRegistry.register(Item1);
已加载的项目将在此服务(或您的任何业务逻辑)中注册自己-这证明已在加载项目:
//registry.ts
export default class GlobalRegistry {
static _items = [];
static register(cls){
console.log('Register class: ', cls.name);
this._items.push(cls.name);
}
static getItems(){
return this._items;
}
}
使用require.context(...)
要求'items'目录下的所有文件:
//index.ts
import GlobalRegistry from './registry';
// Import all files under './items/*.ts'
var context = require.context('./items', true, /\.ts$/);
context.keys().forEach((key) => {
context(key);
});
console.log('Loaded classes:', GlobalRegistry.getItems());
最后,为了让TypeScript满意,我们声明了Webpack提供的require.context()
接口:
//references.d.ts
// Extend @types/node NodeRequire type to define Webpack's context function
declare interface NodeRequire {
context: (dir: string, includeSubdirs: boolean, filter: RegExp) => any;
}
// Tell TypeScript that there is a global `require` variable available to us
declare var require: NodeRequire;
应用程序运行时,您应该会看到以下信息:
Register class: Item1
Register class: Item2
Register class: Item3
Loaded classes: (3) ["Item1", "Item2", "Item3"]
1。包含顺序 如果您先引用单个类,则不能保证包含的顺序。
例如,如果您明确导入类型并将其用作值,则该类型将在仅通过require.context(...)
包含的其他类型之前加载。
示例-使用Item2作为值:
//index.ts
/* require.context(...) stuff is here */
import {Item2} from './items/Item2';
let myItem = new Item2(); // use Item2 as a value
更改加载顺序:
Register class: Item2
Register class: Item1
Register class: Item3
Loaded classes: (3) ["Item2", "Item1", "Item3"]
但是请注意,仅按类型(而不是按值)引用不会更改加载顺序
let myItem: Item2; // just referencing by type won't affect load order
2。需要功能依赖项警告
在构建期间,您可能会收到警告,例如:require function is used in a way in which dependencies cannot be statically extracted
。
不一定有什么错误,只是Webpack会让您知道您正在使用require
做一些时髦的事情-这是真的:)
执行此动态要求可能会影响捆绑软件的摇树或其他静态分析(即,如果不使用这些类型,则不能从捆绑软件中排除这些类型)。但这不必手动管理文件导入,这可能是一个公平的取舍-您必须根据自己的需求/项目目标进行评估。