对TypeScript的接口和类编码准则感到困惑


79

我阅读了TypeScript编码指南

我发现这句话令人费解:

不要使用“ I”作为接口名称的前缀

我的意思是,如果没有“ I”前缀,这样的事情将毫无意义

class Engine implements IEngine

我是否缺少明显的东西?

我不太了解的另一件事是:

班级

为了保持一致性,请勿在核心编译器管道中使用类。请改用函数闭包。

那说明我根本不应该使用类吗?

希望有人可以帮我清理一下:)


12
要澄清的是,这是有关TypeScript代码样式的文档,而不是有关如何实现项目的样式指南。如果使用I前缀对您和您的团队有意义,请使用它。如果没有,也许Java风格的SomeThing(接口)和SomeThingImpl(实现)都可以使用它。
布罗科2015年

噢,那说明不少东西:)
Snæbjørn

当然可以):),我将评论作为答案移了下来
Brocco

2
编码准则的美丽之处在于它们是准则,因此您可以选择是否实施。我个人I用来表示一个界面,因为它是我所习惯的,并且对我团队中的人们来说是有意义的。
乔恩·普里斯

3
当我的团队开始使用TS时,我们还使用I-prefix作为接口。我认为是C#的影响。然后,我阅读TypeScript团队关于不使用I前缀的指南。我花了几个星期才意识到这一点。我一直在急切地寻找信息,说明为什么他们有这样的规则。一段时间后,我意识到:接口的I前缀是一个缺陷(至少在TypeScript中),它带来的问题多于带来的好处。
Stanislav Berkov

Answers:


159

当团队/公司交付框架/编译器/工具集时,他们已经具有一些经验和最佳实践。他们将其作为准则。准则是 建议。如果您不喜欢它们,可以忽略它们。编译器仍然会编译您的代码。虽然在罗马...

这就是我的愿景,为什么TypeScript团队建议不使用I前缀接口。

原因#1匈牙利表示法的时代已经过去

I-prefix-for-interface支持者的主要观点是,前缀有助于立即查看(窥视)类型是否为接口。前缀有助于立即进行(偷看)的声明吸引了匈牙利符号I接口名称,C类,A抽象类,s字符串变量,cconst变量,i整数变量的前缀。我同意这种名称修饰可以为您提供键入信息,而无需将鼠标悬停在标识符上方或通过热键导航到类型定义。匈牙利符号缺点和下面提到的其他原因远远超过了这种微小的好处。匈牙利符号未在当代框架中使用。C#有I由于历史原因(COM),接口的前缀(这是C#中唯一的前缀)。回顾一下,.NET架构师之一(Brad Abrams)认为最好不要使用Iprefix。TypeScript不具有COM传统功能,因此没有I-prefix-for-interface规则。

原因#2-I前缀违反封装原理

假设您有一些黑匣子。您将获得一些类型引用,该引用可让您与该框进行交互。您不必关心它是接口还是类。您只需使用其界面部分。要求知道它是什么(接口,特定实现或抽象类)违反了封装。

示例:假设您需要在代码中修复API设计误区:接口作为合同,例如删除ICar接口并改用Car基类。然后,您需要在所有使用者中执行此类替换。I-prefix导致使用者暗中依赖黑盒实现细节。

原因#3防止命名错误

开发人员懒于正确考虑名称。命名是计算机科学两大难题之一。当开发人员需要提取接口时,只需将字母添加I到类名中就很容易,您将获得一个接口名。禁止I使用接口前缀会迫使开发人员竭尽全力为接口选择合适的名称。选择的名称不仅应在前缀上不同,而且应强调意图差异。

抽象情况:你应该不会没有定义的ICar接口和相关的Car类。Car是一种抽象,应该是用于合同的一种。实现应具有描述性的独特名称,例如SportsCar, SuvCar, HollowCar

很好的例子:WpfeServerAutosuggestManager implements AutosuggestManagerFileBasedAutosuggestManager implements AutosuggestManager

错误的例子: AutosuggestManager implements IAutosuggestManager

原因#4正确选择的名称会给您接种API设计神话:接口即合同

在我的实践中,我遇到了很多人,他们在具有Car implements ICar命名方案的单独接口中无意中重复了类的接口部分。在单独的接口类型中复制类的接口部分不会神奇地将其转换为抽象。您仍将获得具体的实现,但是具有重复的接口部分。如果您的抽象不是很好,那么复制接口部分将无法改善它。提取抽象是艰苦的工作。

注意:在TS中,您不需要用于模拟类或重载功能的单独接口。可以使用TypeScript实用程序类型来代替创建描述类的公共成员的单独接口,而不必使用其他接口。例如,Required<T>构造一个由type的所有公共成员组成的type T

export class SecurityPrincipalStub implements Required<SecurityPrincipal> {
  public isFeatureEnabled(entitlement: Entitlement): boolean {
      return true;
  }
  public isWidgetEnabled(kind: string): boolean {
      return true;
  }

  public areAdminToolsEnabled(): boolean {
      return true;
  }
}

如果要构造排除某些公共成员的类型,则可以使用Omit和Exclude的组合


3
我喜欢您在命名具体类时要比接口名称更具体的观点,但是认为I前缀有助于立即了解类型是否具有实现。使用接口的主要优点是不将外部代码的实现细节耦合到特定的实现。
cchamberlain

1
@demisx如果感觉很尴尬,那么您不应该这样做。回答问题:您真的需要它们吗?它们会发出任何感觉,还是您只是出于对正确进行工程的错误认识而使用它们?
斯坦尼斯拉夫·贝尔科夫

2
尽管您的观点在理论上听起来不错,但实际情况是,在足够大的团队中,通常将“ I”前缀替换为“ Impl”后缀
jameslk

3
@jameslk我知道事物命名不IImpl是硬(“只有两种计算机科学坚硬的东西:缓存失效和命名的事情”菲尔- Karlton),但是是可行的。
斯坦尼斯拉夫·贝尔科夫

5
我同意删除I通常会通过在实现中添加前缀或后缀来代替:DefaultFooService或FoodServiceImpl。使用前缀,您会感到困惑,而且合同与实现/抽象之间没有重叠的命名问题。同样,重复点是有效的,但是接口的点是具有契约,并且能够用其他东西代替实现。通常,这在单元测试中绝对至关重要……更不用说抽象和不变性的好处了。。
克里斯(Chris)

45

关于您引用的链接的说明:

这是有关TypeScript代码样式的文档,而不是有关如何实现项目的样式指南。

如果使用I前缀对您和您的团队有意义,请使用它(我愿意)。

如果没有,也许Java风格的SomeThing(接口)和SomeThingImpl(实现)都可以使用它。


18
只是为了澄清。Typescript手册仍说: In general, do not prefix interfaces with I (e.g. IColor). Because the concept of an interface in TypeScript is much more broad than in C# or Java, the IFoo naming convention is not broadly useful.并不严格,但看起来很推荐。
古里亚

3
同意。听起来确实像Microsoft的所有基于TypeScript的项目的代码指南,而不仅仅是TypeScript本身。我们发现该指南非常令人困惑,并且仍然在所有接口前面加上“ I”。
demisx

3
我认为可以保留一些方案I。在一个React工程中,有Card一个是接口,一个是的组件Card。在道具中,我需要一个数组Card,但类型不是组件。我必须选择命名ICard还是CardComponent...
BrunoLM '17

3
SomeThingImpl implements SomeThing和一样好SomeThing implements ISomeThing。如果SomeThing是抽象,则命名应为Concrete[Some]Thing implements SomeThing
Stanislav Berkov

正如@Guria所说,我认为TypeScript手册已经说明了一切,我们只需要注意这些示例,我们就会知道如何很好地使用它。
giovannipds

1

作为接口的类型是实现细节。实现细节应隐藏在API:s中。这就是为什么你应该避免I

您应避免同时使用prefix suffix。这些都是错误的:

  • ICar
  • CarInterface

您应该做的是在API中显示一个漂亮的名称,并在实现中隐藏一个实现细节。这就是为什么我建议:

  • Car -API中公开的接口。
  • CarImpl -对使用者隐藏的该API的实现。

目前,我还利用了从我的SpringBoot背景建立的这种结构。因此,这在TS中被认为是正确的吗?在TS社区中,对于什么是正确的问题似乎有很多意见,而没有明确的答案。
杂质

2
使用Impl后缀会产生副作用,即用IBob叔叔替换所有以您为荣的前缀。
SzczepanHołyszewski
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.