2013-09-23 70 views
106

我在看打字稿代碼後發現,他們使用打字稿任何VS對象

interface Blablabla { 

    field: Object; 

} 

什麼是使用對象VS 任何的利益,如

interface Blablabla { 

    field: any; 

} 

回答

109

對象是比任何更多的限制。那就是:

interface MyInterface { 

    b: Object; 
} 

var foo = (a : MyInterface) => alert(a.b.nomethod()); 

編譯,因爲Object沒有nomethod()功能。如果在界面中使用any而不是Object,則會進行編譯。

簡而言之,any可以是任何東西(你可以調用任何方法等沒有編譯錯誤)。如果您明確使用Object,則只能使用Object類中定義的方法等。

+0

我正在使用使用Object的外部定義文件。有沒有辦法擴展它,讓編譯器接受字符串? – Jay

12

對象似乎是比任何更具體的聲明。從打字稿規範(第3部分):

在打字稿所有類型都稱爲 任何類型的單個頂部類型的亞型。 any關鍵字引用這種類型。 Any類型是 一種可以表示任何沒有約束的JavaScript值的類型。 所有其他類型被分類爲基本類型,對象類型或 類型參數。這些類型在其值上引入了各種靜態約束條件。

另外:

的任何類型的用於表示任何JavaScript值。 的值任何類型都支持與JavaScript中的值相同的操作,並且對任何 值的操作都執行最小靜態類型檢查。具體來說,任何名稱的屬性都可以通過 來訪問。可以使用任何參數列表將任何值和任何值作爲函數或 調用。

對象不允許相同的靈活性。

例如:

var myAny : any; 

myAny.Something(); // no problemo 

var myObject : Object; 

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

很好的回答,可以更好地顯示出缺乏靈活性 – basarat

+2

編輯。也許不是最好的修正,但至少是真實的。 :) –

22

any是特定於TypeScript的東西是由亞歷克斯的答案解釋得很好。

Object指的是JavaScript object類型。通常用作{}或有時new Objectjavascript中的大部分內容與它們繼承的對象數據類型兼容。但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; 
13

相反。NET中所有類型派生自一個「對象」,在TypeScript中,所有類型派生自「任何」。我只是想添加這個比較,因爲我認爲這將是一個普通的比較,因爲更多的.NET開發人員嘗試使用TypeScript。

145

位舊,但不傷害添加一些筆記。

當你寫這樣的事情

var a: any; 
var b: Object; 
var c: {}; 
  • 一個沒有接口,它可以是任何東西,編譯器知道任何有關它的成員訪問時這麼最小的類型檢查完成/既能分配本身及其成員。基本上,你告訴編譯器「退後,我知道我在做什麼,所以只相信我」;
  • b具有對象接口,因此只能在該接口中定義的成員可用於b。它仍然是JavaScript,所以一切都會擴展Object;
  • c extends Type與TypeScript中的其他任何東西一樣,但不添加任何成員。由於TypeScript中的類型兼容性基於結構子類型,而不是標稱子類型,所以c最終與b相同,因爲它們具有相同的接口:Object接口。

這就是爲什麼

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任何東西的意圖(也許你會在運行時檢查類型來決定如何處理它做),請記住,

  • ,編譯器將讓你做你想要PARAM什麼;
  • FB,編譯器將只允許您訪問對象的成員,你會最終不得不做了很多類型轉換的有...

所以,基本上,當你不知道類型,與任何並做運行時類型檢查。

顯然,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,在範圍之外,我只是想澄清一下,任何應該只用於你不知道什麼來臨,以及任何其他你應該註釋正確的類型。

UPDATE:

Typescript 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

有沒有人知道*爲什麼他們決定添加'{}',然後如果他們已經有'對象'? (反之亦然,以先到者爲準)有一些細微差別,對吧? – CletusW

+2

'{}'是定義(內聯)接口的常用方式,只是在這種情況下,您正在定義一個沒有成員的接口。在響應中很好地解釋了這個細微差別:「''''擴展了'Object',就像TypeScript中的其他任何東西一樣。 – DanielM

+0

我想投票給你的行_So,基本上,當你不知道類型時,用'any'去做運行時類型檢查。不要使用'any',而應該使用union你正在檢查的類型:'TypeA | InterfaceB | string'。如果您還有未知類型的默認情況,請在聯合中添加「{}」或「Object」。 – ILMTitan

0

添加到亞歷克斯的答案和簡化它:

對象是更嚴格的使用,因此給出了p程序員更多的編譯時間「評估」能力,因此在很多情況下提供了更多的「檢查能力」,並且可以防止任何泄漏,而任何更通用的術語以及大量的編譯時檢查可能因此被忽略。

0

試試這個:

private a: Object<any> = {}; 

constructor() { 
    a.name = "foo"; 
} 
+0

僅限代碼答案因爲他們沒有解釋他們如何解決問題而不鼓勵。請更新您的答案,以解釋這個問題已經具有的其他已接受和已獲得解答的答案是如何改進的。此外,這個問題已經有4年的歷史了,您的努力會得到最近沒有答案的用戶的讚賞。請複習[我如何寫出一個好答案](https://stackoverflow.com/help/how-to-answer)。 – FluffyKitten