What to use for data-only objects in TypeScript: Class or Interface?

Use classes with parameter properties:

// Immutable data object
class Person {
  constructor(readonly firstName: String, readonly lastName: String) {}
}

// Mutable data object
class Person {
  constructor(public firstName: String, public lastName: String) {}
}

Interface and it's not even close.

People start writing TypeScript and they suddenly think they have to use classes for some reason. But they don't. Classes are an ES6 feature and they work fine, but if it's just data, it's just data.

A major problem with using classes is that they won't serialize/deserialize like you expect over the wire, so things like instanceof checks won't work.

One rule of thumb is that if there's not internal state associated with some methods, and there's no need for traditional OO polymorphism, don't use a class. This even extends to static classes -- use namespace / module instead.