'any' vs 'Object'


210

Eu estou olhando para o código TypeScript e notei que eles usam:

interface Blablabla {

   field: Object;

}

Qual é o benefício de usar Objectvs any, como em:

interface Blablabla {

  field: any;

}

Respostas:


202

Objecté mais restritivo que any. Por exemplo:

let a: any;
let b: Object;

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

A Objectclasse não tem uma nomethod()função, portanto, o transpiler irá gerar um erro dizendo exatamente isso. Se você usar, anybasicamente está dizendo ao transpilador que tudo vale, você não está fornecendo informações sobre o que está armazenado a- pode ser qualquer coisa! E, portanto, o transpiler permitirá que você faça o que quiser com algo definido como any.

Então, em suma

  • any pode ser qualquer coisa (você pode chamar qualquer método etc sem erros de compilação)
  • Objectexpõe as funções e propriedades definidas na Objectclasse.

285

Um pouco velho, mas não faz mal adicionar algumas notas.

Quando você escreve algo assim

let a: any;
let b: Object;
let c: {};
  • a não tem interface, pode ser qualquer coisa, o compilador não sabe nada sobre seus membros; portanto, nenhuma verificação de tipo é executada ao acessar / atribuir a ele e a seus membros. Basicamente, você está dizendo ao compilador para " recuar, eu sei o que estou fazendo, então apenas confie em mim ";
  • b possui a interface Object, portanto, APENAS os membros definidos nessa interface estão disponíveis para b . Ainda é JavaScript, então tudo estende Object;
  • c estende Object, como qualquer outra coisa no TypeScript, mas não adiciona membros. Como a compatibilidade de tipo no TypeScript é baseada em subtipo estrutural, não subtipo nominal, c acaba sendo o mesmo que b porque eles têm a mesma interface: a interface Objeto.

E é por isso

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 porque

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

Portanto, Objecte {}são equivalentes no TypeScript.

Se você declarar funções como estas

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

com a intenção de aceitar qualquer coisa para param (talvez você verifique os tipos em tempo de execução para decidir o que fazer com ele), lembre-se de que

  • dentro de fa , o compilador permitirá que você faça o que quiser com param ;
  • dentro de fb , o compilador permitirá apenas que você faça referência aos membros do Object .

Vale ressaltar, porém, que se o param aceita vários tipos conhecidos, uma abordagem melhor é declará-lo usando tipos de união, como em

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

Obviamente, as regras de herança de OO ainda se aplicam, portanto, se você deseja aceitar instâncias de classes derivadas e tratá-las com base em seu tipo base, como em

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

o tipo de base é a maneira de fazê-lo, não qualquer . Mas isso é OO, fora do escopo, eu só queria esclarecer que qualquer um só deve ser usado quando você não sabe o que está por vir e, para qualquer outra coisa, anote o tipo correto.

ATUALIZAR:

Typescript 2.2 adicionado um objecttipo, que especifica que o valor é um não-primitivo: (ou seja, não é um number, string, boolean, symbol, undefined, ou null).

Considere as funções definidas como:

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

xterá as mesmas propriedades disponíveis em todas essas funções, mas é um erro de tipo chamar dcom uma primitiva:

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

2
Alguém sabe por que eles decidiram adicionar {}se já tinham Object? (ou vice-versa, o que ocorrer primeiro) Deve haver uma pequena diferença, certo?
CletusW

4
{}é a maneira normal de definir interfaces (em linha), apenas que, neste caso, você está definindo uma interface sem membros. A pequena diferença está bem explicada na resposta: " {}se estende Objectcomo qualquer outra coisa no TypeScript".
DanielM

7
Eu quero votar em você para a linha Então, basicamente, quando você não souber o tipo, vá com anye faça a verificação do tipo em tempo de execução. Não use any, em vez usar uma união dos tipos que você está navegando contra: TypeA|InterfaceB|string. Se você também tiver um caso padrão para um tipo desconhecido, adicione {}ou Objectà união.
ILMTitan

Os documentos datilografados às vezes são confusos, por exemplo, 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 fizeram pensar que nem mesmo a ligação toStringé permitida, quando na verdade acho que eles pretendiam dizer exist at runtimedepois de ler a resposta.
Olga

24

any é algo específico do TypeScript, que é explicado muito bem pela resposta de alex.

Objectrefere-se ao objecttipo JavaScript . Comumente usado como {}ou às vezes new Object. A maioria das coisas em javascript são compatíveis com o tipo de dados do objeto à medida que são herdadas. Mas o TypeScriptany é específico e compatível com tudo nas duas direções (sem herança). por exemplo :

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
Sua resposta é bastante vaga e mesclada Objecte objectque são tipos diferentes no TypeScript.
M93a

@ m93a: Você pode expandir qual é a diferença entre Objecte objectno TS?
Alexander Abakumov

4
Esta é provavelmente a melhor fonte para aprender a diferença. O ponto principal é que objecté um tipo para tudo que não é primitivo, enquanto Objecté uma interface que contém coisas comuns como toStringessas. O número 42seria um, Objectmas não um object.
m93a

20

Ao contrário do .NET, onde todos os tipos derivam de um "objeto", no TypeScript, todos os tipos derivam de "qualquer". Eu só queria adicionar essa comparação, pois acho que ela será comum, à medida que mais desenvolvedores .NET experimentarem o TypeScript.


16

O objeto parece ser uma declaração mais específica do que qualquer outra. Na especificação TypeScript (seção 3):

Todos os tipos no TypeScript são subtipos de um único tipo superior chamado Qualquer tipo. A palavra-chave any faz referência a esse tipo. O tipo Qualquer é o tipo que pode representar qualquer valor JavaScript sem restrições. Todos os outros tipos são categorizados como tipos primitivos, tipos de objeto ou parâmetros de tipo. Esses tipos introduzem várias restrições estáticas em seus valores.

Além disso:

O tipo Qualquer é usado para representar qualquer valor JavaScript. Um valor do tipo Qualquer suporta as mesmas operações que um valor em JavaScript e a verificação mínima de tipo estático é executada para operações nos valores Qualquer. Especificamente, propriedades de qualquer nome podem ser acessadas por meio de um valor Qualquer e Qualquer valor pode ser chamado como função ou construtor com qualquer lista de argumentos.

Objetos não permitem a mesma flexibilidade.

Por exemplo:

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

Adicionando a resposta de Alex e simplificando-a:

Os objetos são mais rigorosos com seu uso e, portanto, dão ao programador mais poder de "avaliação" em tempo de compilação e, portanto, em muitos casos, fornecem mais "capacidade de verificação" e podem evitar vazamentos, enquanto qualquer um é um termo mais genérico e muito compilado as verificações de tempo podem, portanto, ser ignoradas.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.