Confused about the Interface and Class coding guidelines for TypeScript Ask Question

Confused about the Interface and Class coding guidelines for TypeScript Ask Question

I read through the TypeScript Coding guidelines

And I found this statement rather puzzling:

Do not use "I" as a prefix for interface names

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:

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

ベストアンサー1

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

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

Reason #1 The times of the Hungarian notation have passed

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.

Reason #2 I-prefix violates encapsulation principle

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 設計の神話: インターフェースは契約であるコード内で、たとえばICarインターフェースを削除し、Car代わりに基本クラスを使用します。次に、すべてのコンシューマーでこのような置き換えを実行する必要があります。I-prefix により、コンシューマーはブラックボックス実装の詳細に暗黙的に依存するようになります。

理由3 不適切な名前付けから保護する

開発者は名前についてきちんと考えるのを怠ります。名前付けはコンピュータサイエンスにおける2つの難しいこと開発者がインターフェースを抽出する必要がある場合、クラス名に文字を追加するだけで簡単にIインターフェース名が得られます。Iインターフェースのプレフィックスを許可しないと、開発者はインターフェースに適切な名前を選択するために頭を悩ませることになります。選択された名前はプレフィックスが異なるだけでなく、意図の違いを強調する必要があります。

抽象化の場合:ないICarインターフェースと関連クラスを定義しないでくださいCarCarは抽象化であり、契約に使用されるものでなければなりません。実装には、説明的で区別しやすい名前が必要です (例 ) SportsCar, SuvCar, HollowCar

良い例え:WpfeServerAutosuggestManager implements AutosuggestManagerFileBasedAutosuggestManager implements AutosuggestManager

悪い例: AutosuggestManager implements IAutosuggestManager.

理由4 適切に選ばれた名前はあなたを予防接種するAPI 設計の神話: インターフェースは契約である

実務では、命名スキームを持つ別のインターフェースでクラスのインターフェース部分を無思慮に複製している人にたくさん会いましたCar implements ICar。別のインターフェース型でクラスのインターフェース部分を複製しても、魔法のように抽象化に変換されるわけではありません。インターフェース部分が複製された状態でも、具体的な実装は得られます。抽象化がそれほど良くない場合は、インターフェース部分を複製しても、抽象化は改善されません。抽象化を抽出するのは大変な作業です。

注意: TSでは、クラスのモックや機能のオーバーロードに別のインターフェースは必要ありません。クラスのパブリックメンバーを記述する別のインターフェースを作成する代わりに、TypeScript ユーティリティ型たとえば、Required<T>型のすべてのパブリック メンバーで構成される型を構築します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;
  }
}

パブリックメンバーを除いた型を構築したい場合は、次のようにします。省略と除外の組み合わせ

おすすめ記事