245

我正在查看 TypeScript 代码并注意到它们使用:

interface Blablabla {

   field: Object;

}

Object使用vs有什么好处any,如:

interface Blablabla {

  field: any;

}
4

6 回答 6

335

有点旧,但添加一些注释并没有什么坏处。

当你写这样的东西

let a: any;
let b: Object;
let c: {};
  • a没有接口,它可以是任何东西,编译器对其成员一无所知,因此在访问/分配给它及其成员时不执行类型检查。基本上,您是在告诉编译器“退后,我知道我在做什么,所以请相信我”;
  • b具有 Object 接口,因此只有在该接口中定义的成员可用于b。它仍然是 JavaScript,所以一切都扩展了 Object;
  • c扩展 Object,就像 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{}是 TypeScript 中的等价物。

如果你声明这样的函数

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

为了接受任何参数(也许你会在运行时检查类型以决定如何处理它),请记住

  • fa内部,编译器会让你用param做任何你想做的事情;
  • fb中,编译器只会让你引用Object的成员。

不过值得注意的是,如果param应该接受多种已知类型,更好的方法是使用联合类型声明它,如

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,超出了范围,我只是想澄清一下,仅当你不知道会发生什么时才应该使用any ,而对于其他任何事情,你应该注释正确的类型。

更新:

Typescript 2.2添加了一个object类型,它指定一个值是非原始的:(即不是 a number, string, boolean, symbol, undefined, or 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
于 2015-03-01T16:03:12.020 回答
230

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()函数,因此转译器将生成一个错误,告诉您确切的信息。如果你改用any它,你基本上是在告诉转译器任何事情都发生了,你没有提供关于存储什么的信息a——它可以是任何东西!因此,转译器将允许您使用定义为any.

所以简而言之

  • any可以是任何东西(您可以在其上调用任何方法等而不会出现编译错误)
  • Object公开类中定义的函数和属性Object
于 2013-09-23T14:28:54.527 回答
26

any亚历克斯的回答很好地解释了 TypeScript 特有的东西。

Object指 JavaScriptobject类型。常用作{}或 有时new Objectjavascript中的大多数东西都与对象数据类型兼容,因为它们继承自它。但是TypeScriptany是特定的并且在两个方向上都兼容(不是基于继承的)。例如:

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;  
于 2013-09-23T23:18:38.817 回答
22

与所有类型都派生自“对象”的 .NET 不同,在 TypeScript 中,所有类型都派生自“任何”。我只是想添加这个比较,因为我认为随着越来越多的 .NET 开发人员尝试使用 TypeScript,这将是一个常见的比较。

于 2013-09-24T15:00:09.563 回答
18

Object 似乎是比任何声明都更具体的声明。来自 TypeScript 规范(第 3 节):

TypeScript 中的所有类型都是称为 Any 类型的单一顶级类型的子类型。any 关键字引用此类型。Any 类型是一种可以无约束地表示任何 JavaScript 值的类型。所有其他类型都归类为原始类型、对象类型或类型参数。这些类型对其值引入了各种静态约束。

还:

Any 类型用于表示任何 JavaScript 值。Any 类型的值支持与 JavaScript 中的值相同的操作,并且对 Any 值的操作执行最少的静态类型检查。具体来说,可以通过 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'.
于 2013-09-23T14:28:52.057 回答
1

添加到亚历克斯的答案并简化它:

对象对它们的使用更加严格,因此给程序员更多的编译时间“评估”能力,因此在很多情况下提供更多的“检查能力”并且可以防止任何泄漏,而任何是一个更通用的术语和大量编译因此,时间检查可能会被忽略。

于 2017-08-18T04:34:24.560 回答