They amount to the same thing in the end, but the former is preferred when possible.
In this case:
var drummer: Musician = {
instrument: "drum",
age: 28
}
you are declaring that drummer is a Musician by using a type annotation, and assigning to it an object literal. The compiler is happy about this because it can verify that yes, the object literal you're assigning is compatible with the Musician interface. It has an string-valued instrument property and a numeric-valued age property.
Now what if we try this:
var drummer: Musician = {};
// ~~~~~~~ <-- error!
// Type '{}' is not assignable to type 'Musician'.
// Property 'instrument' is missing in type '{}'.
drummer.instrument = "drum"
drummer.age = 28
The assignment of an empty object literal to a value declared as a Musician causes a compiler error. After all, an empty object literal does not have an string-valued instrument property or a numeric-valued age property. And you're being warned about that. Now, you know that the next two lines will fix that problem, but the compiler doesn't.
So you can change it to use a type assertion instead of a type annotation:
var drummer = <Musician>{}; // okay
drummer.instrument = "drum"
drummer.age = 28
The assertion is where you tell the compiler "this object is really a Musician, even though right now it doesn't look like it." You're taking on the responsibility of ensuring that drummer is a Musician and relieving the compiler of the responsibility of verifying that for you.
And since the next two lines add the required properties, everything is fine.
The former is preferable because you usually want the compiler to verify your types if it can. A type assertion gives up some safety, which is fine until it isn't, like driving an automobile without a seat belt:
var drummer = <Musician>{}; // okay
drummer.age = 28;
// whoops, forgot the instrument, but TypeScript isn't complaining
// ... later ...
console.log(drummer.instrument.toUpperCase());
// no error at compile time
// but blows up at runtime
There are times when you have to use type assertions. For example, when you have some kind of circular reference where you need to build the object in pieces:
interface MarriedPerson extends Person {
spouse: MarriedPerson
}
var adam: MarriedPerson = {
age: 0,
// spouse: eve <-- can't do this before eve is defined
} as MarriedPerson;
var eve: MarriedPerson = {
age: 0,
spouse: adam
}
adam.spouse = eve; // okay now
In the above, each MarriedPerson needs a reference to a MarriedPerson... but there won't be one until you've created one. So you are forced to resort to having a short period of time where one of the MarriedPerson objects does not have the required spouse. And thus assertions are required.
Does that make sense? Hope it helps; good luck!