typescript - 'any' vs 'Object'
Jag tittar på TypeScript-kod och märkte att de använder:
interface Blablabla {
field: Object;
}
Vilken är fördelen med att använda Object jämfört med any, som i:
interface Blablabla {
field: any;
}
Svar #1
Lite gammal, men det skadar inte att lägga till några anteckningar.
När du skriver något sånt här
let a: any;
let b: Object;
let c: {};
- a har inget gränssnitt, det kan vara vad som helst, kompilatorn vet ingenting om dess medlemmar så ingen typkontroll utförs när man får åtkomst till/ tilldelar både det och dess medlemmar. I princip säger du till kompilatorn: "backa, jag vet vad jag gör, så lita bara på mig";
- b har Object-gränssnittet, så ENDAST de medlemmar som definieras i det gränssnittet är tillgängliga för b. Det är fortfarande JavaScript, så allt utökar Object;
- c utökar Object, precis som allt annat i TypeScript, men lägger inte till några medlemmar. Eftersom typkompatibilitet i TypeScript baseras på strukturell subtypning, inte nominell subtypning, blir c till slut samma som b eftersom de har samma gränssnitt: Object-gränssnittet.
Och det är därför
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
och varför
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
Så Object och {} är ekvivalenta i TypeScript.
Om du deklarerar funktioner som dessa
function fa(param: any): void {}
function fb(param: Object): void {}
med avsikten att acceptera vad som helst för param (kanske tänker du kontrollera typer vid körningstid för att avgöra vad du ska göra med det), kom ihåg det
- inne i fa kommer kompilatorn låta dig göra vad du vill med param;
- inne i fb kommer kompilatorn bara låta dig referera till Objects medlemmar.
Det är dock värt att notera att om param ska acceptera flera kända typer, är ett bättre tillvägagångssätt att deklarera det med unionstyper, som i
function fc(param: string|number): void {}
Självklart gäller fortfarande OO-ärvningsregler, så om du vill acceptera instanser av härledda klasser och behandla dem baserat på deras basklass, som i
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..
bas typen är sättet att göra det på, inte any. Men det är OO, utanför omfattningen, jag ville bara klargöra att any endast bör användas när du inte vet vad som kommer, och för allt annat bör du ange rätt typ.
UPPDATERING :
Typescript 2.2 lade till en object-typ, som anger att ett värde är icke-primärt: (dvs. inte en number, string, boolean, symbol, undefined eller null).
Betrakta funktioner definierade som:
function b(x: Object) {}
function c(x: {}) {}
function d(x: object) {}
x kommer att ha samma tillgängliga egenskaper inom alla dessa funktioner, men det är ett typfel att kalla d med en primitiv:
b("foo"); //Okay
c("foo"); //Okay
d("foo"); //Error: "foo" is a primitive
Svar #2
Object är mer begränsande än any. Till exempel:
let a: any;
let b: Object;
a.nomethod(); // Transpiles just fine
b.nomethod(); // Error: Property 'nomethod' does not exist on type 'Object'.
Klassen Object har ingen funktion nomethod(), därför kommer transpileraren att generera ett fel som säger exakt det. Om du istället använder any säger du i princip till transpileraren att allt är tillåtet, du ger ingen information om vad som lagras i a - det kan vara vad som helst! Och därför kommer transpileraren att låta dig göra vad du vill med något som definieras som any.
Så kort sagt
anykan vara vad som helst (du kan kalla vilken metod som helst etc på det utan kompilationsfel)Objectexponerar funktionerna och egenskaperna som definieras iObject-klassen.
Svar #3
any är något specifikt för TypeScript förklaras ganska bra av alexs svar.
Object hänvisar till JavaScript-typen object. Vanligtvis används som {} eller ibland new Object. De flesta saker i javascript är kompatibla med objekt-datatypen eftersom de ärvs från den. Men any är TypeScript-specifik och kompatibel med allt i båda riktningarna (inte baserat på arv). t.ex. :
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;
Svar #4
I motsats till .NET där alla typer härstammar från ett "object", härstammar i TypeScript alla typer från "any". Jag ville bara lägga till denna jämförelse eftersom jag tror att det kommer att vara en vanlig jämförelse när fler .NET-utvecklare provar TypeScript.
Svar #5
Objekt verkar vara en mer specifik deklaration än any. Från TypeScript-specifikationen (sektion 3):
Alla typer i TypeScript är underordnade en enda överordnad typ som kallas Any-typen. Nyckelordet any refererar till denna typ. Any-typen är den enda typen som kan representera vilket JavaScript-värde som helst utan begränsningar. Alla andra typer kategoriseras som primitiva typer, objekttyper eller typparametrar. Dessa typer introducerar olika statiska begränsningar på deras värden.
Också :
Typen Any används för att representera vilket JavaScript-värde som helst. Ett värde av typen Any stödjer samma operationer som ett värde i JavaScript och minimal statisk typkontroll utförs för operationer på Any-värden. Specifikt kan egenskaper med vilket namn som helst nås genom ett Any-värde och Any-värden kan anropas som funktioner eller konstruktörer med vilken argumentlista som helst.
Objekt tillåter inte samma flexibilitet.
Till exempel:
var myAny : any;
myAny.Something(); // no problemo
var myObject : Object;
myObject.Something(); // Error: The property 'Something' does not exist on value of type 'Object'.
