TypeScriptのインターフェイスファイル定義に基づいてオブジェクトを作成するにはどうすればよいですか?


313

私はこのようなインターフェースを定義しました:

interface IModal {
    content: string;
    form: string;
    href: string;
    $form: JQuery;
    $message: JQuery;
    $modal: JQuery;
    $submits: JQuery;
 }

私はこのような変数を定義します:

var modal: IModal;

しかし、モーダルのプロパティを設定しようとすると、次のようなメッセージが表示されます

"cannot set property content of undefined"

インターフェイスを使用してモーダルオブジェクトを記述しても問題ありませんか?

回答:


426

「モーダル」変数を別の場所で作成していて、TypeScriptにすべて実行されることを伝えたい場合は、次のようにします。

declare const modal: IModal;

TypeScriptで実際にIModalのインスタンスになる変数を作成する場合は、完全に定義する必要があります。

const modal: IModal = {
    content: '',
    form: '',
    href: '',
    $form: null,
    $message: null,
    $modal: null,
    $submits: null
};

または、型のアサーションを使用してうそをつきますが、予期しない場所で未定義になり、場合によってはランタイムエラーなど、アクセス時に型の安全性が失われますmodal.content(コントラクトに記載されているプロパティが存在します)。

const modal = {} as IModal;

クラスの例

class Modal implements IModal {
    content: string;
    form: string;
    href: string;
    $form: JQuery;
    $message: JQuery;
    $modal: JQuery;
    $submits: JQuery;
}

const modal = new Modal();

あなたは「それは本当にインターフェースの複製だ」と思うかもしれません-そしてあなたは正しいです。ModalクラスがIModalインターフェイスの唯一の実装である場合、インターフェイスを完全に削除して使用することができます...

const modal: Modal = new Modal();

のではなく

const modal: IModal = new Modal();

2
ありがとう。最初はすべてのモーダルコンテンツを定義する必要がないようにしたいと思っていました。インターフェイスの代わりに、Modalをプロパティを持つクラスとして定義し、新しいコンストラクターを使用してすべての初期値を設定した方が簡単でしょうか?

1
はい-クラスを定義して、必要なときに新しいインスタンスを作成するだけで済みます。例が必要ですか?
フェントン2012年

2
インターフェースの例とメモを追加しました。
フェントン2012年

21
var modal = <IModal>{};これは私が探していたものです;-)ありがとう!
Legends

5
参考までに、{} as IModalよりも使用することをお勧めします<IModal>{}<foo>JSXでスタイルアサーションを使用すると、言語文法のあいまいさが解消されます。続きを読む。そしてもちろん、letまたはのconst代わりにを使用してくださいvar
Alex Klaus

191

インターフェースの空のオブジェクトが必要な場合は、次のようにします。

var modal = <IModal>{};

データを構造化するためにクラスの代わりにインターフェースを使用する利点は、クラスにメソッドがない場合、コンパイルされたJSで空のメソッドとして表示されることです。例:

class TestClass {
    a: number;
    b: string;
    c: boolean;
}

コンパイルする

var TestClass = (function () {
    function TestClass() {
    }
    return TestClass;
})();

価値はありません。一方、インターフェースはJSにはまったく表示されませんが、データ構造化と型チェックの利点は提供されます。


1
`上記のコメントに追加します。関数 "updateModal(IModal modalInstance){}"を呼び出すには、次のように、インターフェイス 'IModal'のインラインインスタンスを作成できます。 {//この行はインスタンスコンテンツを作成します: ''、フォーム: ''、href: ''、$ form:null、$ message:null、$ modal:null、$ submits:null}); //コードを完成させます `
Sunny

を使用しvar modal= <abc>{}て、空のオブジェクトのabc型のモーダルを割り当てただけですが、どこでモーダルの型を宣言しましたか?私はtypescript6を使用しています。
Pardeep Jain

これは私にとってはうまくいきませんでした。受け入れられた回答で述べられているように、オブジェクト全体を初期化する必要がありました。
Rahul Sonwanshi


22

基本的には、5つの異なるオプションがあると思います。それらの中から選択することは、達成したい目標によっては簡単かもしれません。

TypeScriptを使用して型チェックを適用しているため、ほとんどの場合、クラス使用してインスタンス化する最善の方法。

interface IModal {
    content: string;
    form: string;
    //...

    //Extra
    foo: (bar: string): void;
}

class Modal implements IModal {
    content: string;
    form: string;

    foo(param: string): void {
    }
}

他のメソッドがインターフェイスからオブジェクトを作成する簡単な方法を提供している場合でも、オブジェクトをさまざまな問題に使用していて、インターフェイスの過剰分離が発生しない場合は、インターフェイスを分割することを検討する必要があります。

interface IBehaviour {
    //Extra
    foo(param: string): void;
}

interface IModal extends IBehaviour{
    content: string;
    form: string;
    //...
}

一方、たとえばコードの単体テスト中に(懸念の分離を頻繁に適用しない場合)、生産性のために欠点を受け入れることができる場合があります。他のメソッドを適用して、主に大規模なサードパーティの* .d.tsインターフェース用のモックを作成できます。そして、すべての巨大なインターフェースに常に完全な匿名オブジェクトを実装することは、骨の折れる作業です。

このパスでは、最初のオプションは空のオブジェクト作成することです:

 var modal = <IModal>{};

次に、インターフェースの必須部分完全に実現します。サードパーティのJavaScriptライブラリを呼び出すかどうかは便利ですが、以前のように、代わりにクラスを作成する必要があると思います。

var modal: IModal = {
    content: '',
    form: '',
    //...

    foo: (param: string): void => {
    }
};

3番目に、インターフェースの一部のみを作成して匿名オブジェクトを作成できますが、この方法で契約を履行する必要があります

var modal: IModal = <any>{
    foo: (param: string): void => {

    }
};

インターフェースがオプションであっても私の回答を要約すると、それらはJavaScriptコードに変換されないため、TypeScriptは、賢く一貫して使用される場合に、新しいレベルの抽象化を提供します。ほとんどの場合、あなた自身のコードからそれらを却下できるからといって、そうすべきではないと私は思います。



12

上に等しい答えが見つからなかったので、私の答えは異なります。私がやります:

modal: IModal = <IModal>{}

2

あなたができるあなたのインターフェースを使用して

class Modal() {
  constructor(public iModal: IModal) {
   //You now have access to all your interface variables using this.iModal object,
   //you don't need to define the properties at all, constructor does it for you.
  }
}

2

ここに別のアプローチがあります:

このようにESLintフレンドリーなオブジェクトを作成するだけです

const modal: IModal = {} as IModal;

または、インターフェースに基づいたデフォルトのインスタンスと、存在する場合は適切なデフォルト

const defaultModal: IModal = {
    content: "",
    form: "",
    href: "",
    $form: {} as JQuery,
    $message: {} as JQuery,
    $modal: {} as JQuery,
    $submits: {} as JQuery
};

次に、いくつかのプロパティをオーバーライドするだけで、デフォルトのインスタンスのバリエーション

const confirmationModal: IModal = {
    ...defaultModal,     // all properties/values from defaultModal
    form: "confirmForm"  // override form only
}

1

これまでに投稿されたソリューションの多くは型アサーションを使用しているため、実装で必要なインターフェイスプロパティが省略されている場合、コンパイルエラーはスローされません。

他の堅牢でコンパクトなソリューションに興味がある人のために:

オプション1:インターフェースを実装する匿名クラスをインスタンス化します。

new class implements MyInterface {
  nameFirst = 'John';
  nameFamily = 'Smith';
}();

オプション2:ユーティリティ関数を作成します。

export function impl<I>(i: I) { return i; }

impl<MyInterface>({
  nameFirst: 'John';
  nameFamily: 'Smith';
})

0

を使用してデフォルト値を設定できますClass

クラスコンストラクターなし:

interface IModal {
  content: string;
  form: string;
  href: string;
  isPopup: boolean;
};

class Modal implements IModal {
  content = "";
  form = "";
  href: string;  // will not be added to object
  isPopup = true;
}

const myModal = new Modal();
console.log(myModal); // output: {content: "", form: "", isPopup: true}

クラスコンストラクター

interface IModal {
  content: string;
  form: string;
  href: string;
  isPopup: boolean;
}

class Modal implements IModal {
  constructor() {
    this.content = "";
    this.form = "";
    this.isPopup = true;
  }

  content: string;

  form: string;

  href: string; // not part of constructor so will not be added to object

  isPopup: boolean;
}

const myModal = new Modal();
console.log(myModal); // output: {content: "", form: "", isPopup: true}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.