TypeScriptのextendingとintersecting interfacesの違い?
質問
以下のような型が定義されているとします。
interface Shape {
color: string;
}
では、この型にさらにプロパティを追加する方法を以下に考えてみましょう。
拡張機能
interface Square extends Shape {
sideLength: number;
}
交差点
type Square = Shape & {
sideLength: number;
}
両方のアプローチの違いは何ですか?
また、完全を期すため、また好奇心からなのですが、同等の結果を得るための他の方法はあるのでしょうか?
どのように解決するのですか?
はい、あなたのシナリオに関連するかしないかの違いがあります。
おそらく最も重要なのは、両方のタイプに存在する場合、同じプロパティ キーを持つメンバーがどのように処理されるかの違いです。
考えてみてください。
interface NumberToStringConverter {
convert: (value: number) => string;
}
interface BidirectionalStringNumberConverter extends NumberToStringConverter {
convert: (value: string) => number;
}
は
extends
は、派生インターフェースと同じキーを持つが互換性のないシグネチャを持つプロパティを宣言しているため、エラーとなります。
error TS2430: Interface 'BidirectionalStringNumberConverter' incorrectly extends interface 'NumberToStringConverter'.
Types of property 'convert' are incompatible.
Type '(value: string) => number' is not assignable to type '(value: number) => string'.
Types of parameters 'value' and 'value' are incompatible.
Type 'number' is not assignable to type 'string'.
しかし、交差型を採用すると
type NumberToStringConverter = {
convert: (value: number) => string;
}
type BidirectionalStringNumberConverter = NumberToStringConverter & {
convert: (value: string) => number;
}
何のエラーもなく、さらに与えられた
// And this is a good thing indeed as a value conforming to the type is easily conceived
const converter: BidirectionalStringNumberConverter = {
convert: (value: string | number) => {
return (typeof value === 'string' ? Number(value) : String(value)) as string & number; // type assertion is an unfortunately necessary hack.
}
}
const s: string = converter.convert(0); // `convert`'s call signature comes from `NumberToStringConverter`
const n: number = converter.convert('a'); // `convert`'s call signature comes from `BidirectionalStringNumberConverter`
これはもう一つの興味深い違いにつながります。
interface
の宣言はオープンエンドです。新しいメンバーはどこにでも追加することができ、複数の
interface
宣言は、同じ宣言空間に同じ名前の宣言が複数あると
マージされます。
.
マージ動作の一般的な使い方は次のとおりです。
lib.d.ts
interface Array<T> {
// map, filter, etc.
}
array-flat-map-polyfill.ts
interface Array<T> {
flatMap<R>(f: (x: T) => R[]): R[];
}
if (typeof Array.prototype.flatMap !== 'function') {
Array.prototype.flatMap = function (f) {
// Implementation simplified for exposition.
return this.map(f).reduce((xs, ys) => [...xs, ...ys], []);
}
}
このように
extends
節が存在しないことに注意してください。別々のファイルで指定されているにもかかわらず、インターフェースは両方ともグローバルスコープにあり、両方のメンバーセットを持つ単一の論理インターフェース宣言に名前によってマージされます。(同じことが、少し異なる構文でモジュールスコープの宣言に対しても可能です)
対照的に、交差型は
type
宣言に格納される交点型は閉じており、マージの対象にはなりません。
多くの相違点があります。TypeScriptハンドブックに、両方の構文について詳しく書かれています。また インターフェイス と 高度なタイプ のセクションは特に関連性が高いです。
関連
-
[解決済み] C#のStringとstringの違いは何ですか?
-
[解決済み] コンストラクタとngOnInitの違いについて
-
[解決済み] Pythonの旧スタイルのクラスと新スタイルのクラスの違いは何ですか?
-
[解決済み] TypeScriptでの取得と設定
-
[解決済み] textとvarcharの違い(character varying)
-
[解決済み】TypeScriptのインターフェースと型について
-
[解決済み】type()とisinstance()の違いは何ですか?)
-
[解決済み] tsconfig.jsonのtargetは何のためにあるのですか?
-
[解決済み] Angular2 - Http POST リクエストパラメータ
-
Array<string>とstring[]の違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】TypeScriptのインターフェースと型について
-
[解決済み] タイプスクリプト。カスタムタイプに対する typeof のチェック
-
[解決済み] typescriptでmoment.jsをインポートするには?
-
[解決済み] spec/testフォルダを使用したtsconfigのセットアップ
-
[解決済み] TSにおける文字列列列挙型と文字列リテラル型の相違点
-
[解決済み] クラス内列挙型(TypeScript定義ファイル)
-
[解決済み] Angular2 canActivate() 非同期関数呼び出し
-
[解決済み] TypeScriptのInterfacesでgetter/setterを使用することは可能ですか?重複
-
[解決済み] TypeScriptのUnion型、Memberの複数型署名
-
[解決済み] 親コンポーネントのプロパティにアクセスする