stackdave
stackdave

Reputation: 7054

typescript can i use class like interface

I have this code:

interface Heroe {
    title:string,
    hero:string,
    ranking:number,
}

export class AppComponent {
  heroe : Heroe = {
     title : 'Tour of Heroes',
     hero : 'Windstorm',
     ranking :1
  }
}

if I replace Class instead Interface code works:

class Heroe {
    title:string,
    hero:string,
    ranking:number,
}

export class AppComponent {
  heroe : Heroe = {
     title : 'Tour of Heroes',
     hero : 'Windstorm',
     ranking :1
  }
}

It's correct to use class like interfaces, when class have no methods, just type of variables, that is not a problem?. In angular demo use this way, have a class and not interface:

https://angular.io/docs/ts/latest/tutorial/toh-pt1.html

in this last case I have a class instead Interface, and have no interface for the class,

the correct would not be have Interface first, then a Class based in the interface ? , but if both have the same name; how typescript which must use ??

Example:

interface Heroe {
    title:string,
    hero:string,
    ranking:number,
}
class Heroe  interface Heroe {
    title:string,
    hero:string,
    ranking:number,
}

export class AppComponent {
  heroe : Heroe = {
     title : 'Tour of Heroes',
     hero : 'Windstorm',
     ranking :1
  }
}

I's ok too have Heroe same name class like interface?

Upvotes: 0

Views: 123

Answers (1)

Nitzan Tomer
Nitzan Tomer

Reputation: 164139

"It's correct to use class like interfaces"
Well, that depends on what you're trying to do, but it's not the same:

class Heroe {
    title: string;
    hero: string;
    ranking: number;

    constructor(title: string, hero: string, ranking: number) {
        this.title = title;
        this.hero = hero;
        this.ranking = ranking;
    }
}

let o1 = new Heroe("title", "hero", 0);
let o2: Heroe = { title: "title", hero: "hero", ranking: 0 }

compiles into:

var Heroe = (function () {
    function Heroe(title, hero, ranking) {
        this.title = title;
        this.hero = hero;
        this.ranking = ranking;
    }
    return Heroe;
}());
var o1 = new Heroe("title", "hero", 0);
var o2 = { title: "title", hero: "hero", ranking: 0 };

(code in playground)

As you can see o1 and o2 are clearly different, one is an instance of the Heroe class and the second is just an object with the same properties as the instance.

It's clear in the console:

console.log(o1); // Heroe {title: "title", hero: "hero", ranking: 0}
console.log(o2); // Object {title: "title", hero: "hero", ranking: 0}

The reason that the compiler doesn't care that o2 is just an object even when declared as Heroe is because:

One of TypeScript’s core principles is that type-checking focuses on the shape that values have. This is sometimes called “duck typing” or “structural subtyping”.

(more about Duck typing)

Or with an example:

function log(heroe: Heroe) {
    console.log(`Title: ${ heroe.title }, Hero: ${ heroe.hero }, Ranking: ${ heroe.ranking }`);
}

log(o1); // obviously this is ok
log(o2); // but this is ok as well

Passing o2 is fine because even if it's not an instance of Heroe it does satisfy the interface for the class.


You can use the same name for an interface and a class, but you can't redeclare properties, so this is not ok:

interface Heroe {
    title: string; // Error: Duplicate identifier 'title'
}

class Heroe {
    title: string; // Error: Duplicate identifier 'title'
}

But this is:

interface Heroe { title: string; }

class Heroe { subtitle: string; }

The order of the declarations doesn't matter, you can have the interface below the class.
You can read more about this in Declaration Merging.

But you can also implement an interface:

interface IHeroe {
    title: string;
    hero: string;
    ranking: number;
}

class Heroe implements IHeroe {
    title: string;
    hero: string;
    ranking: number;
}

Upvotes: 2

Related Questions