「任意」と「オブジェクト」


209

私はTypeScriptコードを見ていて、それらが使用していることに気づきました:

interface Blablabla {

   field: Object;

}

使用することの利点は何であるObjectanyのように、:

interface Blablabla {

  field: any;

}

回答:


202

Objectはより制限的ですany。例えば:

let a: any;
let b: Object;

a.nomethod(); // Transpiles just fine
b.nomethod(); // Error: Property 'nomethod' does not exist on type 'Object'.

Objectクラスはありませんnomethod()ので、transpilerは、まさにそれを伝えるエラーが発生します、機能を。any代わりに使用する場合、基本的にトランスパイラーに何かが起こっていることを伝えているので、何が格納されているかについての情報は提供されていませんa。したがって、トランスパイラーを使用すると、として定義されanyたものを使用して、何でも好きなことができます。

要するに

  • any 何でもかまいません(コンパイルエラーなしでメソッドなどを呼び出すことができます)
  • ObjectObjectクラスで定義された関数とプロパティを公開します。

283

少し古いですが、メモを追加しても問題ありません。

このようなものを書くとき

let a: any;
let b: Object;
let c: {};
  • aにはインターフェースがなく、何でもかまいません。コンパイラーはそのメンバーについて何も認識していないため、そのメンバーとそのメンバーの両方にアクセス/割り当てするときに型チェックは実行されません。基本的に、あなたはコンパイラーに「取り消す、私がやっていることを知っているので、私を信頼してくださいと言っています。
  • bにはObjectインターフェースがあるため、そのインターフェースで定義されたメンバーのみがbで使用できます。それはまだJavaScriptなので、すべてがオブジェクトを拡張します。
  • cはTypeScriptの他のオブジェクトと同様にObjectを拡張しますが、メンバーは追加しません。TypeScriptの型の互換性は、名義的なサブタイプではなく構造的なサブタイプに基づいているため、cは同じインターフェイス(オブジェクトインターフェイス)を持っているため、bと同じになります。

そしてそれが理由です

a.doSomething(); // Ok: the compiler trusts you on that
b.doSomething(); // Error: Object has no doSomething member
c.doSomething(); // Error: c neither has doSomething nor inherits it from Object

なぜ

a.toString(); // Ok: whatever, dude, have it your way
b.toString(); // Ok: toString is defined in Object
c.toString(); // Ok: c inherits toString from Object

だから、Object{}活字体で等価物です。

このような関数を宣言すると

function fa(param: any): void {}
function fb(param: Object): void {}

paramの何かを受け入れることを意図して(おそらく、実行時に型をチェックして、それをどうするかを決定する予定です)、

  • fa内では、コンパイラーはparamを使用して必要なことをすべて実行できます。
  • fb内では、コンパイラーはObjectのメンバーのみを参照できます。

ただし、paramが複数の既知の型を受け入れることになっている場合、より良いアプローチは、次のようにunion型を使用して宣言することです。

function fc(param: string|number): void {}

明らかに、OO継承ルールが引き続き適用されるため、派生クラスのインスタンスを受け入れ、基本タイプに基づいてそれらを処理する場合は、次のようにします。

interface IPerson {
    gender: string;
}

class Person implements IPerson {
    gender: string;
}

class Teacher extends Person {}

function func(person: IPerson): void {
    console.log(person.gender);
}

func(new Person());     // Ok
func(new Teacher());    // Ok
func({gender: 'male'}); // Ok
func({name: 'male'});   // Error: no gender..

基本タイプはそれを行う方法であり、はありませ。しかし、のOOは、スコープの外に、私はちょうどことを明確にしたいとどれかがあなたが来ていただきました!を知らない場合にのみ使用しなければならない、と何かのためにあなたが正しい型に注釈を付ける必要があります。

更新:

2.2活字体添加object型、値が非プリミティブであることを指定します(すなわちないnumberstringbooleansymbolundefined、またはnull)。

次のように定義された関数を考えます。

function b(x: Object) {}
function c(x: {}) {}
function d(x: object) {}

xこれらのすべての関数内で使用可能なプロパティは同じですdが、プリミティブで呼び出すのはタイプエラーです。

b("foo"); //Okay
c("foo"); //Okay
d("foo"); //Error: "foo" is a primitive

2
すでに追加しているのに、なぜ追加することにしたのか誰か知っ{}ていObjectますか?(またはその逆、どちらが先か)若干の違いがあるはずですよね?
CletusW 2017年

4
{}(インライン)インターフェースを定義する通常の方法ですが、この場合のみ、メンバーのないインターフェースを定義します。わずかな違いはよく対応して説明されている:「{}拡張Object活字体で何か他のもののように、」。
DanielM 2017年

7
行に反対票を投じたいので、基本的に、型がわからない場合は、any実行時に型チェックを行ってください。を使用しないでくださいany。代わりに、チェックする型の和集合を使用してくださいTypeA|InterfaceB|string。不明なタイプのデフォルトのケースもある場合は、{}またはObjectユニオンに追加します。
ILMTitan 2018

Typescriptのドキュメントは時々紛らわしいことがあります。たとえば、実際にあなたが答えを読んだ後に言うBut variables of type Object only allow you to assign any value to them - you can’t call arbitrary methods on them, even ones that actually exist:つもりだったと思うのに、呼び出しさえtoString許可されていないと私に思わせましたexist at runtime
オルガ

24

any TypeScriptに固有の何かはアレックスの答えによって非常によく説明されています。

ObjectJavaScript objectタイプを参照します。一般に、{}または時々使用されnew Objectます。JavaScriptのほとんどのものは、オブジェクトデータ型から継承するため、オブジェクトデータ型と互換性があります。ただしanyTypeScript固有であり、双方向ですべてに互換性があります(継承ベースではありません)。例:

var foo:Object; 
var bar:any;
var num:number;

foo = num; // Not an error
num = foo; // ERROR 

// Any is compatible both ways 
bar = num;
num = bar;  

1
あなたの答えは非常に曖昧で混合Objectobjectあり、TypeScriptの異なる型です。
m93a

@ m93a:TS Objectとの違いは何objectですか?
Alexander Abakumov

4
これはおそらく違いを知るための最良の情報源です。主なポイントは、objectプリミティブではないすべてのもののタイプでObjectあり、一般的なものなどを含むインターフェースですtoString。番号42はですが、Objectではありませんobject
m93a

20

TypeScriptでは、すべての型が「オブジェクト」から派生する.NETとは対照的に、すべての型は「任意」から派生します。この比較を追加したかったのは、より多くの.NET開発者がTypeScriptを試してみるのと同じように行われると思うからです。


16

オブジェクトはどの宣言よりも具体的な宣言のようです。TypeScript仕様(セクション3)から:

TypeScriptのすべての型は、Any型と呼ばれる単一のトップ型のサブタイプです。anyキーワードはこのタイプを参照します。Anyタイプは、制約なしで任意のJavaScript値を表すことができる1つのタイプです。他のすべての型は、プリミティブ型、オブジェクト型、または型パラメーターとして分類されます。これらのタイプは、値にさまざまな静的制約を導入します。

また:

Anyタイプは、任意のJavaScript値を表すために使用されます。Any型の値はJavaScriptの値と同じ操作をサポートし、Any値の操作に対して最小限の静的型チェックが実行されます。具体的には、任意の名前のプロパティにはAny値を介してアクセスでき、任意の値は任意の引数リストを使用して関数またはコンストラクターとして呼び出すことができます。

オブジェクトは同じ柔軟性を許可しません。

例えば:

var myAny : any;

myAny.Something(); // no problemo

var myObject : Object;

myObject.Something(); // Error: The property 'Something' does not exist on value of type 'Object'.

0

アレックスの答えに加えてそれを簡素化する:

オブジェクトはその使用に関してより厳密であり、したがって、プログラマーにコンパイル時間の「評価」能力を提供します。したがって、多くの場合、「チェック機能」を提供し、リークを防ぐことができますが、より一般的な用語と多くのコンパイルしたがって、時間チェックは無視される可能性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.