对 TypeScript 的接口和类编码指南感到困惑
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31876947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Confused about the Interface and Class coding guidelines for TypeScript
提问by Sn?bj?rn
I read through the TypeScript Coding guidelines
我通读了TypeScript 编码指南
And I found this statement rather puzzling:
我发现这个陈述相当令人费解:
Do not use "I" as a prefix for interface names
不要使用“I”作为接口名称的前缀
I mean something like this wouldn't make a lot of sense without the "I" prefix
我的意思是,如果没有“I”前缀,这样的事情就没有多大意义
class Engine implements IEngine
Am I missing something obvious?
我错过了一些明显的东西吗?
Another thing I didn't quite understand was this:
我不太明白的另一件事是:
Classes
For consistency, do not use classes in the core compiler pipeline. Use function closures instead.
班级
为保持一致性,请勿在核心编译器管道中使用类。改用函数闭包。
Does that state that I shouldn't use classes at all?
这是否表明我根本不应该使用类?
Hope someone can clear it up for me :)
希望有人能帮我清理一下:)
回答by Stanislav Berkov
When a team/company ships a framework/compiler/tool-set they already have some experience, set of best practices. They share it as guidelines. Guidelines are recommendations. If you don't like any you can disregard them. Compiler still will compile yourcode. Though when in Rome...
当一个团队/公司发布一个框架/编译器/工具集时,他们已经有了一些经验,一套最佳实践。他们将其分享为指导方针。指南是 建议。如果你不喜欢任何你可以忽略它们。编译器仍然会编译你的代码。虽然在罗马时...
This is my vision why TypeScript team recommends not I
-prefixing interfaces.
这就是我为什么 TypeScript 团队不推荐I
-prefixing 接口的原因。
Reason #1 The times of the Hungarian notationhave passed
原因 #1匈牙利符号的时代已经过去
Main argument from I
-prefix-for-interface supporters is that prefixing is helpful for immediately grokking (peeking) whether type is an interface. Statement that prefix is helpful for immediately grokking (peeking) is an appeal to Hungarian notation. I
prefix for interface name, C
for class, A
for abstract class, s
for string variable, c
for const variable, i
for integer variable. I agree that such name decoration can provide you type information without hovering mouse over identifier or navigating to type definition via a hot-key. This tiny benefit is outweighed by Hungarian notationdisadvantages and other reasons mentioned below. Hungarian notation is not used in contemporary frameworks. C# has I
prefix (and this the only prefix in C#) for interfaces due to historical reasons (COM). In retrospect one of .NET architects (Brad Abrams) thinks it would have been better not using I
prefix. TypeScript is COM-legacy-free thereby it has no I
-prefix-for-interface rule.
I
-prefix-for-interface 支持者的主要论点是前缀有助于立即了解(窥视)类型是否为接口。前缀有助于立即探索(peeking)的声明是对匈牙利符号的呼吁。I
接口名称、C
类、A
抽象类、s
字符串变量、c
const 变量、i
整数变量的前缀。我同意这样的名称修饰可以为您提供类型信息,而无需将鼠标悬停在标识符上或通过热键导航到类型定义。这个微小的好处被匈牙利符号的缺点和下面提到的其他原因所抵消。现代框架中不使用匈牙利符号。C#有I
由于历史原因 (COM),接口的前缀(这是 C# 中唯一的前缀)。回想起来,一位 .NET 架构师 (Brad Abrams) 认为最好不要使用I
prefix。TypeScript 是 COM-legacy-free 的,因此它没有I
-prefix-for-interface 规则。
Reason #2 I
-prefix violates encapsulation principle
原因#2 I
-prefix 违反封装原则
Let's assume you get some black-box. You get some type reference that allows you to interact with that box. You should not care if it is an interface or a class. You just use its interface part. Demanding to know what is it (interface, specific implementation or abstract class) is a violation of encapsulation.
让我们假设你得到了一些黑匣子。您会获得一些类型引用,允许您与该框进行交互。你不应该关心它是一个接口还是一个类。您只需使用它的界面部分。要求知道它是什么(接口、具体实现或抽象类)是违反封装的。
Example: let's assume you need to fix API Design Myth: Interface as Contractin your code e.g. delete ICar
interface and use Car
base-class instead. Then you need to perform such replacement in all consumers. I
-prefix leads to implicit dependency of consumers on black-box implementation details.
示例:假设您需要在代码中修复API 设计神话:接口作为合同,例如删除ICar
接口并改用Car
基类。然后您需要在所有消费者中执行此类替换。I
-prefix 导致消费者对黑盒实现细节的隐式依赖。
Reason #3 Protection from bad naming
原因 #3 防止错误命名
Developers are lazy to think properly about names. Naming is one of the Two Hard Things in Computer Science. When a developer needs to extract an interface it is easy to just add the letter I
to the class name and you get an interface name. Disallowing I
prefix for interfaces forces developers to strain their brains to choose appropriate names for interfaces. Chosen names should be different not only in prefix but emphasize intent difference.
开发人员懒得正确考虑名称。命名是计算机科学中的两件难事之一。当开发人员需要提取接口时,只需将字母添加I
到类名称中即可轻松获得接口名称。不允许I
接口前缀迫使开发人员绞尽脑汁为接口选择合适的名称。选择的名称不仅应在前缀上不同,而且应强调意图差异。
Abstraction case: you should notnot define an ICar
interface and an associated Car
class. Car
is an abstraction and it should be the one used for the contract. Implementations should have descriptive, distinctive names e.g. SportsCar, SuvCar, HollowCar
.
抽象情况:你应该不会没有定义的ICar
接口和相关的Car
类。Car
是一种抽象,它应该是用于合同的抽象。实现应该具有描述性的、独特的名称,例如SportsCar, SuvCar, HollowCar
.
Good example: WpfeServerAutosuggestManager implements AutosuggestManager
, FileBasedAutosuggestManager implements AutosuggestManager
.
很好的例子:WpfeServerAutosuggestManager implements AutosuggestManager
,FileBasedAutosuggestManager implements AutosuggestManager
。
Bad example: AutosuggestManager implements IAutosuggestManager
.
不好的例子:AutosuggestManager implements IAutosuggestManager
。
Reason #4 Properly chosen names vaccinate you against API Design Myth: Interface as Contract.
原因 #4 正确选择的名称可以让您免受API 设计误区的影响:Interface as Contract。
In my practice, I met a lot of people that thoughtlessly duplicated interface part of a class in a separate interface having Car implements ICar
naming scheme. Duplicating interface part of a class in separate interface type does not magically convert it into abstraction. You will still get concrete implementation but with duplicated interface part. If your abstraction is not so good, duplicating interface part will not improve it anyhow. Extracting abstraction is hard work.
在我的实践中,我遇到了很多人,他们在一个具有Car implements ICar
命名方案的单独接口中不加思索地复制了一个类的接口部分。在单独的接口类型中复制类的接口部分并不会神奇地将其转换为抽象。你仍然会得到具体的实现,但接口部分是重复的。如果你的抽象不是那么好,复制界面部分无论如何也不会改进它。提取抽象是一项艰巨的工作。
NOTE: In TS you don't need separate interface for mocking classes or overloading functionality.
Instead of creating a separate interface that describes public members of a class you can use TypeScript utility types. E.g. Required<T>
constructs a type consisting of all public members of type T
.
注意:在 TS 中,您不需要单独的接口来模拟类或重载功能。您可以使用TypeScript 实用程序类型,而不是创建一个单独的接口来描述类的公共成员。例如,Required<T>
构造一个由 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;
}
}
If you want to construct a type excluding some public members then you can use combination of Omit and Exclude.
如果要构造一个排除某些公共成员的类型,则可以使用Omit 和 Exclude 的组合。
回答by Brocco
Clarification regarding the link that you reference:
关于您引用的链接的说明:
This is the documentation about the style of the code for TypeScript, and not a style guideline for how to implement your project.
这是关于 TypeScript 代码风格的文档,而不是关于如何实现你的项目的风格指南。
If using the I
prefix makes sense to you and your team, use it (I do).
如果使用I
前缀对您和您的团队有意义,请使用它(我愿意)。
If not, maybe the Java style of SomeThing
(interface) with SomeThingImpl
(implementation) then by all means use that.
如果没有,那么SomeThing
(接口)与SomeThingImpl
(实现)的 Java 风格可能就一定要使用它。
回答by Tomas Bjerre
The type being an interface is an implementation detail. Implementation details should be hidden in API:s. That is why you should avoid I
.
作为接口的类型是实现细节。实现细节应该隐藏在 API:s 中。这就是为什么你应该避免I
.
You should avoid both prefix
andsuffix
. These are both wrong:
您应该避免同时使用prefix
和suffix
。这两个都是错误的:
ICar
CarInterface
ICar
CarInterface
What you should do is to make a pretty name visible in the API and have a the implemtation detail hidden in the implementation. That is why I propose:
您应该做的是在 API 中显示一个漂亮的名称,并在实现中隐藏实现细节。这就是为什么我建议:
Car
- An interface that is exposed in the API.CarImpl
- An implementation of that API, that is hidden from the consumer.
Car
- 在 API 中公开的接口。CarImpl
- 该 API 的实现,对消费者隐藏。
回答by giovannipds
TypeScript's handbooksays it all. Just pay attention to the examples there and be happy. <3
TypeScript 的手册说明了一切。只要注意那里的例子,就会开心。<3