2024-09-22 07:00:03

any和Object

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

interface Blablabla {

   field: Object;

}

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

interface Blablabla {

  field: any;

}

当前回答

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

当你这样写的时候

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

其他回答

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

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

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

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

当你这样写的时候

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

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

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;