【问题标题】:TypeScript - How to check if object implements interface at compile-time?TypeScript - 如何在编译时检查对象是否实现接口?
【发布时间】:2019-05-07 15:54:07
【问题描述】:

问题

假设我有两个文件 - 一个接口文件(如 C 中的头文件)和一个实现文件。

intf.ts(接口文件):

export default interface
{
  foo(baz: number): boolean
  bar(baz: number): string
};

impl.ts(实现文件):

export default
{
  foo(baz: number): boolean
  {
    return baz > 0;
  }

  bar(baz: number): string
  {
    return baz > 0 ? "john" : "doe"
  }
};

如何确定impl.ts 的默认导出是否实现intf.ts 的默认导出?假设我无法修改这些文件中的任何一个。

类似:

import intf from `./intf.ts`;
import impl from `./impl.ts`;

if (impl implements intf)
  console.log("Good input!");
else
  console.log("Bad input! Input does not implement interface!");

注意:答案确实必须在打字稿脚本中确定。


我的部分工作解决方案

这是我想出的一个部分可行的解决方案:

check_if_implements.ts

import intf from `./intf.ts`;
import impl from `./impl.ts`;

function check(_: intf) {};
check(impl);

如果实现未实现接口,此脚本将产生编译时错误。

然后我可以编译这个脚本并检查是否有错误来确定答案。

这有一个问题:如何(在代码中)将“未实现”错误与任何其他错误区分开来?


我为什么要这样做?

我正在尝试学习干净的架构,而 TypeScript 可以很好地与干净的架构配合使用,因为它具有静态类型检查功能。例如,依赖注入在 TypeScript 中很容易做到。

我的计划是每个“模块”(实体、用例、接口实现等)都有一个“接口”和“实现”文件(就像问题中一样)。

当模块依赖于其他模块时,而不是依赖于名称和版本(如 npm 中的"package_name": "^1.0.2"),模块依赖于某个接口。模块可以从现有模块中复制接口或创建自己的接口。

这个想法是任何实现都可以插入到需要接口实现的模块中。我喜欢称其为“静态依赖注入”,当然“运行时依赖注入”仍应在任何有意义的地方使用。

所以现在这需要我确定静态注入的实现是否实现了接口。


感谢您的任何意见!

【问题讨论】:

  • 我想你会想使用 TypeScript 提供的 Compiler API 来编写一个程序来检查实现是否满足接口。
  • @IngoBürk 啊,有趣,我不知道它存在。我会看看它。谢谢

标签: typescript interface


【解决方案1】:

您可以在类型系统中对此进行全面检查。您可以使用import('module') 获取模块的类型并在那里形成,如果实现不正确,您可以构建一个会出错的类型:

type Check<T extends import('./intf').default> = T;
type IsOk = Check<typeof import('./impl')['default']>

【讨论】:

  • 但这会有同样的问题,即导致编译时错误,必须以某种方式进行解析,不是吗?
  • @IngoBürk 这是真的.. 我可能没有完全理解 op 试图做什么.. 它是一个构建时解决方案.. 不确定如何检测错误,也许添加type Check&lt;T extends import('./intf').default | "Implements interf.ts"&gt; = T; 类型中的标记,因此错误将是 Type '{ foo(baz: number): boolean; barr(baz: number): string; }' does not satisfy the constraint 'I | "Implements interf.ts"'. 以便更容易查找..
  • 这看起来可能是最好的解决方案,但我会拭目以待,看看是否还有其他解决方案。感谢您的帮助
  • @DavidCallanan 当然,不急,其他人可能有更好的想法。如果您在解决方案方面需要任何帮助,请告诉我 :)
猜你喜欢
  • 2016-02-21
  • 1970-01-01
  • 2013-04-07
  • 1970-01-01
  • 2016-09-29
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
相关资源
最近更新 更多