'tout' vs 'objet'


210

Je regarde le code TypeScript et j'ai remarqué qu'ils utilisent:

interface Blablabla {

   field: Object;

}

Quel est l'avantage d'utiliser Object vs any, comme dans:

interface Blablabla {

  field: any;

}

Réponses:


202

Objectest plus restrictif que any. Par exemple:

let a: any;
let b: Object;

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

La Objectclasse n'a pas de nomethod()fonction, donc le transpilateur générera une erreur vous disant exactement cela. Si vous utilisez à la anyplace, vous dites au transpilateur que quelque chose se passe, vous ne fournissez aucune information sur ce qui est stocké a- cela peut être n'importe quoi! Et donc le transpilateur vous permettra de faire ce que vous voulez avec quelque chose défini comme any.

Bref

  • any peut être n'importe quoi (vous pouvez appeler n'importe quelle méthode, etc. sans erreurs de compilation)
  • Objectexpose les fonctions et propriétés définies dans la Objectclasse.

285

Un peu vieux, mais ça ne fait pas de mal d'ajouter quelques notes.

Lorsque vous écrivez quelque chose comme ça

let a: any;
let b: Object;
let c: {};
  • a n'a pas d'interface, il peut être n'importe quoi, le compilateur ne sait rien de ses membres, donc aucune vérification de type n'est effectuée lors de l'accès / affectation à la fois à lui et à ses membres. Fondamentalement, vous dites au compilateur de " reculer, je sais ce que je fais, alors faites-moi confiance ";
  • b a l'interface d'objet, donc SEULEMENT les membres définis dans cette interface sont disponibles pour b . C'est toujours JavaScript, donc tout étend Object;
  • c étend Object, comme toute autre chose dans TypeScript, mais n'ajoute aucun membre. Étant donné que la compatibilité des types dans TypeScript est basée sur le sous-typage structurel, et non sur le sous-typage nominal, c finit par être le même que b car ils ont la même interface: l'interface d'objet.

Et c'est pourquoi

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

et pourquoi

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

Donc, Objectet {}sont équivalents dans TypeScript.

Si vous déclarez des fonctions comme celles-ci

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

avec l'intention d'accepter quoi que ce soit pour param (peut-être que vous allez vérifier les types au moment de l'exécution pour décider quoi en faire), rappelez-vous que

  • à l'intérieur de fa , le compilateur vous permettra de faire tout ce que vous voulez avec param ;
  • à l'intérieur de fb , le compilateur ne vous permettra de référencer que les membres d' Object .

Il convient de noter, cependant, que si param est censé accepter plusieurs types connus, une meilleure approche consiste à le déclarer à l'aide de types d'union, comme dans

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

De toute évidence, les règles d'héritage OO s'appliquent toujours, donc si vous souhaitez accepter des instances de classes dérivées et les traiter en fonction de leur type de base, comme dans

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

le type de base est le moyen de le faire, pas n'importe lequel . Mais c'est OO, hors de portée, je voulais juste préciser que tout ne devrait être utilisé que lorsque vous ne savez pas ce qui va arriver, et pour toute autre chose, vous devez annoter le type correct.

METTRE À JOUR:

Tapuscrit 2.2 a ajouté un objecttype, qui spécifie que la valeur est non-primitive: (c. -à- pas un number, string, boolean, symbol, undefined, ou null).

Considérez les fonctions définies comme:

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

xaura les mêmes propriétés disponibles dans toutes ces fonctions, mais c'est une erreur de type à appeler davec une primitive:

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

2
Est-ce que quelqu'un sait pourquoi ils ont décidé d'ajouter {}alors s'ils l'avaient déjà fait Object? (ou vice versa, selon la première éventualité) Il doit y avoir une légère différence, non?
— CletusW

4
{}est la manière normale de définir des interfaces (en ligne), seulement que dans ce cas, vous définissez une interface sans membres. La légère différence est bien expliquée dans la réponse: " {}s'étend Object, comme toute autre chose en TypeScript".
— DanielM

7
Je veux vous voter contre pour la ligne Donc, fondamentalement, lorsque vous ne connaissez pas le type, allez-y anyet faites une vérification de type au moment de l'exécution. Ne pas utiliser any, utilisez plutôt une union des types que vous archivez contre: TypeA|InterfaceB|string. Si vous avez également un cas par défaut pour un type inconnu, ajoutez l'un {}ou l' autre Objectà l'union.
— ILMTitan

Les documents dactylographiés sont parfois déroutants, par exemple, cela 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:m'a fait penser que même appeler toStringn'est pas autorisé, alors qu'en fait je pense qu'ils voulaient dire exist at runtimeaprès avoir lu votre réponse.
— Olga

24

any est quelque chose de spécifique à TypeScript est expliqué assez bien par la réponse d'Alex.

Objectfait référence au objecttype JavaScript . Couramment utilisé comme {}ou parfois new Object. La plupart des éléments en javascript sont compatibles avec le type de données d'objet car ils en héritent. Mais il anyest spécifique à TypeScript et compatible avec tout dans les deux sens (non basé sur l'héritage). par exemple :

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
Votre réponse est assez vague et mélange Objectet objectqui sont de différents types dans TypeScript.
— m93a

@ m93a: Pouvez-vous développer quelle est la différence entre Objectet objectdans TS?
— Alexander Abakumov

4
C'est probablement la meilleure source pour apprendre la différence. Le point principal est qu'il objects'agit d'un type pour tout ce qui n'est pas primitif, tandis que Objectc'est une interface qui contient des choses courantes comme toStringet telles. Le nombre 42serait un Objectmais pas un object.
— m93a

20

Contrairement à .NET où tous les types dérivent d'un "objet", dans TypeScript, tous les types dérivent de "tout". Je voulais juste ajouter cette comparaison car je pense que ce sera une comparaison courante, car plus de développeurs .NET donneront à TypeScript un essai.


16

L'objet semble être une déclaration plus spécifique que n'importe quelle autre. De la spécification TypeScript (section 3):

Tous les types de TypeScript sont des sous-types d'un seul type supérieur appelé type Any. Le mot clé any fait référence à ce type. Le type Any est le type qui peut représenter n'importe quelle valeur JavaScript sans contrainte. Tous les autres types sont classés en types primitifs, types d'objets ou paramètres de type. Ces types introduisent diverses contraintes statiques sur leurs valeurs.

Aussi:

Le type Any est utilisé pour représenter n'importe quelle valeur JavaScript. Une valeur de type Any prend en charge les mêmes opérations qu'une valeur en JavaScript et une vérification de type statique minimale est effectuée pour les opérations sur toutes les valeurs. Plus précisément, les propriétés de n'importe quel nom sont accessibles via une valeur Any et toutes les valeurs peuvent être appelées en tant que fonctions ou constructeurs avec n'importe quelle liste d'arguments.

Les objets ne permettent pas la même flexibilité.

Par exemple:

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

Ajout à la réponse d'Alex et simplification:

Les objets sont plus stricts avec leur utilisation et donnent donc au programmeur plus de puissance "d'évaluation" de temps de compilation et donc dans de nombreux cas fournissent plus de "capacité de vérification" et peuvent empêcher toute fuite, alors que tout est un terme plus générique et beaucoup de compilation les contrôles horaires pourraient donc être ignorés.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.