“任何”与“对象”


Answers:


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 可以是任何东西(您可以在上面调用任何方法,而不会产生编译错误)
  • Object公开Object类中定义的功能和属性。

283

有点老了,但是添加一些笔记并没有什么坏处。

当你写这样的东西

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

基本类型是执行此操作的方法,而不是任何方法。但这是面向对象的,超出范围,我只是想澄清一下,仅当您不知道即将发布的内容时才应使用任何一种,对于其他任何内容,您都应标注正确的类型。

更新:

打字稿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

4
{}是定义(内联)接口的常规方法,只是在这种情况下,您定义的是没有成员的接口。响应中的细微差别已得到很好的解释:“ 与TypeScript中的其他内容一样,{}extends Object一样”。
DanielM

7
我想对这一行投反对票,因此,基本上,当您不知道类型时,请继续any进行运行时类型检查。不要使用any,而是使用您要检查的类型的并集:TypeA|InterfaceB|string。如果您还具有未知类型的默认大小写,则将{}或添加Object到联合。
ILMTitan

打字稿文档有时会令人困惑,例如,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 alex的答案很好地解释了TypeScript特有的东西。

Object指的是JavaScript object类型。通常用作{}或有时使用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;  

1
您的答案很模糊且混在一起Objectobject并且TypeScript中的类型不同。
m93a '18

@ m93a:您能谈谈TS ObjectobjectTS 之间的区别吗?
亚历山大·阿巴库莫夫

4
可能是了解差异的最佳来源。最主要的一点是,它object是所有非原始类型的类型,而Object接口是包含诸如此类之类的常见事物的接口toString。该数字42将是,Object但不是object
m93a

20

与.NET中所有类型均源自“对象”的相反,在TypeScript中,所有类型均源自“ any”。我只是想添加此比较,因为随着更多.NET开发人员尝试TypeScript,这将是一个普通的比较。


16

对象似乎是比任何对象都更具体的声明。根据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'.

0

添加到Alex的答案并简化它:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.