'any' vs 'Object'


210

Estoy mirando el código TypeScript y noté que usan:

interface Blablabla {

   field: Object;

}

¿Cuál es el beneficio de usar Objectvs any, como en:

interface Blablabla {

  field: any;

}

Respuestas:


202

Objectes más restrictiva que any. Por ejemplo:

let a: any;
let b: Object;

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

La Objectclase no tiene una nomethod()función, por lo tanto, el transpilador generará un error diciéndole exactamente eso. Si usas en su anylugar, básicamente le estás diciendo al transpilador que todo vale, no estás proporcionando información sobre lo que está almacenado a, ¡puede ser cualquier cosa! Y, por lo tanto, el transpilador te permitirá hacer lo que quieras con algo definido como any.

En resumen

  • any puede ser cualquier cosa (puede llamar a cualquier método, etc. sin errores de compilación)
  • Objectexpone las funciones y propiedades definidas en la Objectclase.

285

Un poco viejo, pero no hace daño agregar algunas notas.

Cuando escribes algo como esto

let a: any;
let b: Object;
let c: {};
  • a no tiene interfaz, puede ser cualquier cosa, el compilador no sabe nada sobre sus miembros, por lo que no se realiza ninguna verificación de tipo al acceder / asignar tanto a él como a sus miembros. Básicamente, le estás diciendo al compilador que " retroceda, sé lo que estoy haciendo, así que confía en mí ";
  • b tiene la interfaz Object, por lo que SOLO los miembros definidos en esa interfaz están disponibles para b . Todavía es JavaScript, por lo que todo extiende Object;
  • c extiende Object, como cualquier otra cosa en TypeScript, pero no agrega miembros. Dado que la compatibilidad de tipos en TypeScript se basa en el subtipo estructural, no en el subtipo nominal, c termina siendo lo mismo que b porque tienen la misma interfaz: la interfaz Object.

Y es por eso

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

y por qué

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

Entonces, Objecty {}son equivalentes en TypeScript.

Si declaras funciones como estas

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

con la intención de aceptar cualquier cosa para el parámetro (tal vez va a verificar los tipos en tiempo de ejecución para decidir qué hacer con él), recuerde que

  • dentro de fa , el compilador te permitirá hacer lo que quieras con param ;
  • dentro de fb , el compilador solo le permitirá hacer referencia a los miembros de Object .

Sin embargo, vale la pena señalar que si se supone que param acepta múltiples tipos conocidos, un mejor enfoque es declararlo usando tipos de unión, como en

function fc(param: string|number): void {}

Obviamente, las reglas de herencia OO aún se aplican, por lo que si desea aceptar instancias de clases derivadas y tratarlas según su tipo base, como en

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

El tipo base es la forma de hacerlo, no ninguna . Pero eso es OO, fuera del alcance, solo quería aclarar que cualquiera debe usarse solo cuando no sabe lo que viene, y para cualquier otra cosa debe anotar el tipo correcto.

ACTUALIZAR:

Letra de imprenta 2.2 añade un objecttipo, que especifica que un valor es un no-primitivo: (es decir, no una number, string, boolean, symbol, undefined, o null).

Considere las funciones definidas como:

function b(x: Object) {}
function c(x: {}) {}
function d(x: object) {}

xtendrá las mismas propiedades disponibles dentro de todas estas funciones, pero es un error de tipo llamar dcon una primitiva:

b("foo"); //Okay
c("foo"); //Okay
d("foo"); //Error: "foo" is a primitive

2
¿Alguien sabe por qué decidieron agregar {}entonces si ya lo habían hecho Object? (o viceversa, lo que ocurra primero) Tiene que haber alguna ligera diferencia, ¿verdad?
— CletusW

44
{}es la forma normal de definir interfaces (en línea), solo que en este caso está definiendo una interfaz sin miembros. La ligera diferencia se explica bien en la respuesta: "se {}extiende Object, como cualquier otra cosa en TypeScript".
— DanielM

77
Quiero rechazar el voto por la línea Entonces, básicamente, cuando no conoces el tipo, ve anyy realiza la verificación de tipo en tiempo de ejecución. No utilizar any, en lugar de utilizar una unión de los tipos que usted está navegando en contra: TypeA|InterfaceB|string. Si también tiene un caso por defecto para un tipo desconocido, ya sea añadir {}o Objectal sindicato.
— ILMTitan

Los documentos mecanografiados a veces son confusos, por ejemplo, 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:me hicieron pensar que incluso las llamadas toStringno están permitidas, cuando en realidad creo que querían decir exist at runtimedespués de leer su respuesta.
— Olga

24

any es algo específico de TypeScript que se explica bastante bien con la respuesta de alex.

Objectse refiere al objecttipo de JavaScript . De uso general como {}o a veces new Object. La mayoría de las cosas en javascript son compatibles con el tipo de datos del objeto, ya que heredan de él. Pero anyes específico de TypeScript y compatible con todo en ambas direcciones (no basado en herencia). p.ej :

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
Su respuesta es bastante vaga y mezcla Objecty objectcuáles son diferentes tipos en TypeScript.
— m93a

@ m93a: ¿Puede ampliar cuál es la diferencia entre Objecty objecten TS?
— Alexander Abakumov

44
Esta es probablemente la mejor fuente para aprender la diferencia. El punto principal es que objectes un tipo para todo lo que no es primitivo, mientras que Objectes una interfaz que contiene cosas comunes como toStringy tal. El número 42sería un Objectpero no un object.
— m93a

20

A diferencia de .NET, donde todos los tipos derivan de un "objeto", en TypeScript, todos los tipos derivan de "cualquiera". Solo quería agregar esta comparación, ya que creo que será muy común a medida que más desarrolladores de .NET prueben TypeScript.


16

El objeto parece ser una declaración más específica que ninguna. De la especificación TypeScript (sección 3):

Todos los tipos en TypeScript son subtipos de un solo tipo superior llamado Cualquier tipo. La palabra clave any hace referencia a este tipo. Cualquier tipo es el único que puede representar cualquier valor de JavaScript sin restricciones. Todos los demás tipos se clasifican como tipos primitivos, tipos de objeto o parámetros de tipo. Estos tipos introducen varias restricciones estáticas en sus valores.

También:

Cualquier tipo se utiliza para representar cualquier valor de JavaScript. Un valor del tipo Any admite las mismas operaciones que un valor en JavaScript y se realiza una verificación de tipo estático mínimo para las operaciones en cualquier valor. Específicamente, se puede acceder a las propiedades de cualquier nombre a través de un valor Any y cualquier valor se puede llamar como funciones o constructores con cualquier lista de argumentos.

Los objetos no permiten la misma flexibilidad.

Por ejemplo:

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

Agregando a la respuesta de Alex y simplificándola:

Los objetos son más estrictos con su uso y, por lo tanto, le dan al programador más poder de "evaluación" en el tiempo de compilación y, por lo tanto, en muchos casos proporcionan más "capacidad de verificación" y pueden evitar fugas, mientras que cualquiera es un término más genérico y mucha compilación Por lo tanto, las verificaciones de tiempo pueden ignorarse.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.