'any' vs 'Object'


210

Sto guardando il codice TypeScript e ho notato che usano:

interface Blablabla {

   field: Object;

}

Qual è il vantaggio di usare Objectvs any, come in:

interface Blablabla {

  field: any;

}

Risposte:


202

Objectè più restrittivo di any. Per esempio:

let a: any;
let b: Object;

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

La Objectclasse non ha una nomethod()funzione, quindi il transpiler genererà un errore che ti dice esattamente questo. Se usi anyinvece stai sostanzialmente dicendo al transpiler che qualcosa va bene, non stai fornendo informazioni su ciò che è memorizzato a- può essere qualsiasi cosa! E quindi il transpiler ti permetterà di fare quello che vuoi con qualcosa definito come any.

Quindi in breve

  • any può essere qualsiasi cosa (puoi chiamare qualsiasi metodo ecc. senza errori di compilazione)
  • Objectespone le funzioni e le proprietà definite nella Objectclasse.

285

Un po 'vecchio, ma non fa male aggiungere alcune note.

Quando scrivi qualcosa del genere

let a: any;
let b: Object;
let c: {};
  • a non ha interfaccia, può essere qualsiasi cosa, il compilatore non sa nulla dei suoi membri, quindi nessun controllo del tipo viene eseguito quando si accede / si assegna sia a esso che ai suoi membri. Fondamentalmente, stai dicendo al compilatore di " arretrare, so cosa sto facendo, quindi fidati di me ";
  • b ha l'interfaccia Object, quindi SOLO i membri definiti in tale interfaccia sono disponibili per b . È ancora JavaScript, quindi tutto estende Object;
  • c estende Object, come qualsiasi altra cosa in TypeScript, ma non aggiunge membri. Poiché la compatibilità dei tipi in TypeScript si basa sul sottotipo strutturale, non sul sottotipo nominale, c finisce per essere uguale a b perché hanno la stessa interfaccia: l'interfaccia dell'oggetto.

Ed ecco perché

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

e perché

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

Quindi Objecte {}sono equivalenti in TypeScript.

Se si dichiarano funzioni come queste

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

con l'intenzione di accettare qualsiasi cosa per param (forse hai intenzione di controllare i tipi in fase di esecuzione per decidere cosa farne), ricorda che

  • dentro fa , il compilatore ti permetterà di fare tutto ciò che vuoi con param ;
  • all'interno di fb , il compilatore ti consentirà solo di fare riferimento ai membri di Object .

Vale la pena notare, tuttavia, che se param dovrebbe accettare più tipi noti, un approccio migliore è dichiararlo utilizzando i tipi di unione, come in

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

Ovviamente, si applicano ancora le regole di ereditarietà OO, quindi se si desidera accettare istanze di classi derivate e trattarle in base al loro tipo di base, come in

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

il tipo di base è il modo di farlo, non nessuno . Ma questo è OO, al di fuori dell'ambito, volevo solo chiarire che qualcuno dovrebbe essere usato solo quando non sai cosa sta arrivando, e per qualsiasi altra cosa dovresti annotare il tipo corretto.

AGGIORNARE:

Tipografico 2.2 aggiunto un objecttipo, che specifica che un valore è un non-primitivo: (cioè non un number, string, boolean, symbol, undefined, o null).

Considera le funzioni definite come:

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

xavrà le stesse proprietà disponibili all'interno di tutte queste funzioni, ma è un errore di tipo chiamare dcon una primitiva:

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

2
Qualcuno sa perché hanno deciso di aggiungere {}allora se lo avevano già fatto Object? (o viceversa, qualunque sia la prima volta) Ci deve essere una leggera differenza, giusto?
Cletus,

4
{}è il modo normale di definire interfacce (inline), solo che in questo caso si sta definendo un'interfaccia senza membri. La leggera differenza è ben spiegata nella risposta: "si {}estende Object, come qualsiasi altra cosa in TypeScript".
DanielM,

7
Voglio votare in negativo per la linea Quindi, fondamentalmente, quando non conosci il tipo, vai avanti anye fai il controllo del tipo di runtime. Non usare any, invece di utilizzare un'unione dei tipi che si stanno controllando contro: TypeA|InterfaceB|string. Se hai anche un caso predefinito per un tipo sconosciuto, aggiungi uno {}o Objectal sindacato.
ILMTitan,

I documenti dattiloscritti a volte sono fonte di confusione, ad esempio 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:mi hanno fatto pensare che anche la chiamata toStringnon sia consentita, quando in realtà penso che intendessero dire exist at runtimedopo aver letto la tua risposta.
Olga,

24

any è qualcosa di specifico per TypeScript è spiegato abbastanza bene dalla risposta di alex.

Objectsi riferisce al objecttipo JavaScript . Comunemente usato come {}o talvolta new Object. La maggior parte delle cose in JavaScript sono compatibili con il tipo di dati oggetto che ereditano da esso. Ma anyè specifico di TypeScript e compatibile con tutto in entrambe le direzioni (non basato sull'ereditarietà). per esempio :

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
La tua risposta è piuttosto vaga e mescola Objecte objectche sono tipi diversi in TypeScript.
m93a,

@ m93a: puoi espandere qual è la differenza tra Objecte objectin TS?
Alexander Abakumov,

4
Questa è probabilmente la migliore fonte per imparare la differenza. Il punto principale è che objectè un tipo per tutto ciò che non è primitivo, mentre Objectè un'interfaccia che contiene cose comuni simili toStringe simili. Il numero42 sarebbe un Objectma non un object.
m93a,

20

Contrariamente a .NET dove tutti i tipi derivano da un "oggetto", in TypeScript tutti i tipi derivano da "qualsiasi". Volevo solo aggiungere questo confronto poiché penso che sarà uno comune fatto mentre più sviluppatori .NET provano TypeScript.


16

L'oggetto sembra essere una dichiarazione più specifica di qualsiasi. Dalle specifiche TypeScript (sezione 3):

Tutti i tipi in TypeScript sono sottotipi di un singolo tipo superiore chiamato Qualsiasi tipo. Qualsiasi parola chiave fa riferimento a questo tipo. Il tipo Any è il tipo che può rappresentare qualsiasi valore JavaScript senza vincoli. Tutti gli altri tipi sono classificati come tipi primitivi, tipi di oggetto o parametri di tipo. Questi tipi introducono vari vincoli statici sui loro valori.

Anche:

Il tipo Any viene utilizzato per rappresentare qualsiasi valore JavaScript. Un valore di Qualsiasi tipo supporta le stesse operazioni di un valore in JavaScript e viene eseguito un controllo minimo del tipo statico per le operazioni su Qualsiasi valore. In particolare, è possibile accedere alle proprietà di qualsiasi nome tramite un valore Qualsiasi e Qualsiasi valore può essere chiamato come funzione o costruttore con qualsiasi elenco di argomenti.

Gli oggetti non consentono la stessa flessibilità.

Per esempio:

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

Aggiungendo alla risposta di Alex e semplificandola:

Gli oggetti sono più rigorosi con il loro uso e quindi danno al programmatore più tempo per la "valutazione" del tempo di compilazione e quindi in molti casi forniscono più "capacità di controllo" e potrebbero prevenire eventuali perdite, mentre ogni è un termine più generico e un sacco di compilazione i controlli del tempo potrebbero quindi essere ignorati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.