2024-09-22 07:00:03

any和Object

我正在看TypeScript代码,并注意到他们使用:

interface Blablabla {

   field: Object;

}

使用Object和any的好处是什么,比如:

interface Blablabla {

  field: any;

}

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

TypeScript中的所有类型都是顶部类型的子类型 任何类型。any关键字引用这种类型。Any类型为 一种可以不受约束地表示任何JavaScript值的类型。 所有其他类型被分类为基本类型、对象类型或 类型参数。这些类型在上引入各种静态约束 它们的值。

另外:

Any类型用于表示任何JavaScript值。的值 任何类型都支持与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'.

对象的限制性比任何对象都强。例如:

let a: any;
let b: Object;

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

Object类没有nmethod()函数,因此转译器将生成一个错误,准确地告诉您这一点。如果你使用any来代替,你基本上是在告诉转译器任何事情都会发生,你没有提供任何关于存储在a中的内容的信息——它可以是任何东西!因此,转译器将允许你对定义为any的东西做任何你想做的事情。

简而言之

Any可以是任何东西(你可以在它上面调用任何方法等而不会出现编译错误) 对象公开Object类中定义的函数和属性。


any是TypeScript特有的东西,alex的回答解释得很好。

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

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;  

与。net中所有类型都派生于“object”相反,在TypeScript中,所有类型都派生于“any”。我只是想添加这个比较,因为我认为随着越来越多的。net开发人员尝试TypeScript,它会成为一个常见的比较。


有点老了,但加点注释也无妨。

当你这样写的时候

let a: any;
let b: Object;
let c: {};

a has no interface, it can be anything, the compiler knows nothing about its members so no type checking is performed when accessing/assigning both to it and its members. Basically, you're telling the compiler to "back off, I know what I'm doing, so just trust me"; b has the Object interface, so ONLY the members defined in that interface are available for b. It's still JavaScript, so everything extends Object; c extends Object, like anything else in TypeScript, but adds no members. Since type compatibility in TypeScript is based on structural subtyping, not nominal subtyping, c ends up being the same as b because they have the same interface: the Object interface.

这就是为什么

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 {}

为了接受param的任何内容(也许您将在运行时检查类型以决定如何处理它),请记住这一点

在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..

基本类型是实现它的方法,而不是任何类型。但这是面向对象的,超出了范围,我只是想澄清,any只应该在您不知道将要发生什么的时候使用,对于其他任何类型,您应该注释正确的类型。

更新:

Typescript 2.2增加了一个对象类型,它指定一个值是非原语的:(即不是数字、字符串、布尔值、符号、未定义或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

补充一下Alex的回答并简化一下:

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


如果你的数据有多个键和值对,那么你必须使用object 因为任何接受任何类型的数据,这意味着在某些情况下它不是更好的。 例如,如果你正在执行两个数字的加法,意味着数据必须指定为数字数据类型,如果你指定字符串,那么我将不会执行正确的加法。 很可能我们不用any