如果您想要 Angular InjectionToken 的名称冲突怎么办?

What if you want name collision for Angular InjectionToken?

目标

我想编写一个使用服务的功能模块。这个功能模块不应该关心这个服务的实现,而是期望它实现一个接口,仅此而已。

注意事项和推论

警告:服务应实现的接口不会由该模块定义。

推论:这个接口应该在哪里定义?

没有 InjectionToken 的提供者

功能模块旨在用于我们组织的许多应用程序。每个都能够以不同的方式实现所需服务的接口。如果出现新的用例,界面可能会发生变化,并提示对功能模块进行更改。

我们确定的设计将此接口放入共享库中。

This article 表明使用 InjectionToken 会导致以下错误 'NullInjectorError: No provider for InjectionToken ...`

我创建了一个 StackBlitz example 来说明上述设置和问题。

研究

above thoughtram article 描述了 OpaqueToken 是如何设计来防止这些字符串的意外冲突的。补充说,后来 InjectionToken 封装了 OpaqueToken 以添加额外的打字稿支持。

我希望为我和我的团队提供打字稿支持,但要有一个允许受控碰撞的令牌。

最小可重现示例

查看此 StackBlitz Controlled Collision Token

次优解

如果将InjectionToken替换为字符串,则可以修复上述示例。

将下面两个(相同的文件)改成这样

export const I_SHARED_SERVICE = new InjectionToken<ISharedService>('i-shared-service.shared');
=> 
export const I_SHARED_SERVICE = 'i-shared-service.shared';

结果是失去了对打字稿的支持。这似乎是倒退了一步。

需要一个村庄才能养成 child 或想出一个好的建筑。

在与我的同事讨论后,我意识到一个接口模块(一个单独的 npm 包)可以解决这个问题。

结果

结果是我得到了我的消费项目、我的特色项目和界面项目。

consuming project: 提供feature module和内部consumer之间的adapter,提供接口project的InjectionToken.

feature project: 提供feature components和consuming interface project的InjectionToken.

接口项目提供接口对应InjectionTokens