ssougnez ssougnez - 2 months ago 20
TypeScript Question

Object versus casted literal object in TypeScript

I don't really know when to use this :

interface IFoo
{
bar: string;
}

...

let array: IFoo[];

array.push(<IFoo>{ bar: "test" });


Or

class Foo
{
bar: string;
}

...

let array: Foo[];
let obj = new Foo();

obj.bar = "test";

array.push(obj);


Ths thing is that I'm coming from the C# world and for me, it is cleaner to do the second way, but it's also tempting to use the first way, although it is not as strict as the second option. Therefore, I'm really struggling, for now, I just have the feeling that I can use the one I want, but I'm pretty sure that there are pros and cons for both of them. Unfortunetaly, I couldn't find anything on google.

Thanks

Answer

In javascript we actually dont have classes, but only plain objects* ("hash-tables"-y) with prototype functionality. Functions are some kind of object (with a bit syntax sugar on top of it).

*(not academically correctly saying, and hiding some things)

Try the below example inside a browser's debugger, do some inspection

var parent = {
   method1: function() { return 1 } ,
   method2: function() { return 2 }
}
var child = Object.create(parent)
child.method2 = function() { return '2a' }

child.__proto__   //shows parent
parent.__proto__  //shows Object (the "root class")
child.method3()   //undefined is not a function
child.method2()   //2a, not 2
child.method1()   //method1 not found, looks at __proto__, returns 1
child.toString    
//looks at child, not found
//looks at child.__proto__ (parent), not found
//looks at child.__proto__.__proto__ (Object), returns function

What classes (from ES2015 and transpilers) roughly do is to shim away a bit of the glue code you'd have to write to get the class behavior/programming-style from other languages, starting from objects and prototypes.

In ES2015, the class declaration creates a "prototype" object, and new (or Object.create**) creates an "instance" object which inherits that propotype.

Now back to typescript...

var a : { b : string }
a.b = '4'

{ b : string } is just an annotation. It goes into the realm of types. Let's say in typescript we have 2 realms, the realm of concrete variables, which end up into the generated code; and the realm of types, which are solely used for assistance/linting, but won't end up in the real JS. { b : string } can be referenced away using either interface or type syntax

type Ta = { b : string } //or
interface Ta { b : string }
var a : Ta

Declaring type annotations (which include interfaces) add zero code into the concrete JS realm.

..on the other hand when you use class, typescript creates both

  • concrete JS code (namely, the prototype object)
  • and also a couple of type realm inhabitants.

TL;DR:

Now to the answer, there's no big problem in any of the 2 ways, but using interfaces (and less classes) leans toward the most common javascript coding style. Some JS schools advocate against the use of classes, since you can mostly achieve the same effect through other patterns.

Comments