对TypeScript的接口和类编码准则感到困惑 [英] Confused about the Interface and Class coding guidelines for TypeScript

查看:90
本文介绍了对TypeScript的接口和类编码准则感到困惑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了 TypeScript编码指南

我发现此语句令人费解:

And I found this statement rather puzzling:


请勿将 I用作接口名称的前缀

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

class Engine implements IEngine

我缺少明显的东西吗?

Am I missing something obvious?

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

Another thing I didn't quite understand was this:


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

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 :)

推荐答案

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

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 your code. Though when in Rome...

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

This is my vision why TypeScript team recommends not I-prefixing interfaces.

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

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 notation disadvantages 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.

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

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.

示例:假设您需要修复 API设计神话:代码中的接口作为合约,例如删除 ICar 接口,并使用 Car 基类。然后,您需要在所有使用者中执行此类替换。 I 前缀导致消费者隐式依赖黑盒实现细节。

Example: let's assume you need to fix API Design Myth: Interface as Contract in 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.

开发人员懒于正确考虑名称。命名是计算机科学中的两件事之一。当开发人员需要提取接口时,只需在类名中添加字母 I 即可,您将获得一个接口名。不允许为接口使用 I 前缀,这会迫使开发人员费劲地为接口选择合适的名称。选择的名称不仅应在前缀上不同,而且应强调意图差异。

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.

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

Abstraction case: you should not not 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.

很好的例子: WpfeServerAutosuggestManager实现了AutosuggestManager FileBasedAutosuggestManager实现AutosuggestManager

错误的例子: AutosuggestManager实现IAutosuggestManager

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

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.

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

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.

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.

这篇关于对TypeScript的接口和类编码准则感到困惑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆