Quick Example of Abstract Classes in TypeScript
Tags: devjournal, typescript
Published: 2023-09-15 04:00:36

---
title: Quick Example of Abstract Classes in TypeScript
published: true
description: Just writing notes on Abstract classes for deeper understanding
tags: journal, typescript
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-09-15 03:47 +0000
---

**In this example we abstract a Card class so we can have Playing cards or Joker Cards
If we were to go further we could create a Game class that accepted one or more of the Card types depending on the game, blackjack, poker, war, etc…**

Interfaces are not required for abstract classes, but can be useful for setting up a root blueprint

```
interface ICard {
  value: number;
  getValue: ()=>number;
  compareTo: (o: ICard) => boolean;
  toString: () => string;
}
```

Abstract class can instantiate its own methods and variables or declare them as required for classes that extend from it.

```
abstract class Card implements ICard {
  value: number;
  constructor(value: number){
    this.value = value;
  }
  getValue(){
    return this.value;
  }
  compareTo(o: Card){
    return this.getValue() > o.getValue();
  }


  // abstract keyword is used to tell classes that extend this class
  // that they have to implement this method
  abstract toString(): string;
}

// Enum is just for setting the type in the next class PlayingCard
enum SUIT {
  Diamonds,
  Clubs,
  Spades,
  Hearts,
}
```

Extending an abstract class means we only have to implement the methods of Card that are marked abstract after that we can customize the methods to fit our needs

```
class PlayingCard extends Card {
  suit: SUIT;

  constructor(value: number, suit: string){
    // since we are extending an abstract class we need to instantiate the   
    // Card class in the constructor with super();
    super(value);
    this.suit = this.convertStringToSuit(suit);
  }

  private convertStringToSuit(suit: string){
    switch(suit){
      case "Diamonds":
        return SUIT.Diamonds;
      case "Clubs":
        return SUIT.Clubs;
      case "Spades":
        return SUIT.Spades;
      case "Hearts":
        return SUIT.Hearts;
      default:
        throw new Error();
    }
  }

  private convertSuitToString(){
    switch(this.suit){
      case SUIT.Diamonds:
        return "Diamonds";
      case SUIT.Clubs:
        return "Clubs";
      case SUIT.Spades:
        return "Spades";
      case SUIT.Hearts:
        return "Hearts";
      default:
        return "";
    }
  }

  toString(): string {
    return String(this.getValue()) + " of " + this.convertSuitToString();
  }
}
```

```
A new class based on Card class that has a unchanging value, but its own color method
class JokerCard extends Card {
  color: string;
  constructor(color: string){
    super(14);
    this.color = color;
  }

  toString(): string {
    return String(this.value) + " " + this.color;
  }
}
```

Instantiating and using both of the classes example

Card is the Abstract class so now we can technically store multiple types of Card objects into a single array

```
const cards: Card[] = [];
cards.push(new PlayingCard(1, "Diamonds"));
cards.push(new JokerCard("Black"))
```

Due to shared Logic between the abstract class Card and PlayingCard and JokerCard the compareTo method is available for comparing the playingcard and JokerCard class

```
console.log(cards[0].compareTo(cards[1])); 
// returns false as 1 is not greater then 14
```

The toString method is also allowed no matter which class object as both were required to implement it.

```
console.log(cards[0].toString()) 
// prints "1 of Diamonds"
console.log(cards[1].toString()) 
// prints "14 Black"
```

I’ve also implemented this in an online editor to see the working example and edit it goto [Card abstractions](https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgJIGE5QCbIN4BQyxyAbnADYCuEAXMiFQLYBG0A3ESQOYRgBqlGvQAUASgC8APkasOXYggD2TAA5YIAFSWidaTDjHJpyFkqUUIcEJxLIwSgMpgoobqKMmAzi7ecAvgQEcCw+UIhgyAgUcF5eyAa4wGqWTBDg8RhYuIR25NR0DMxsULYkyiBhVAgOUCL5wkVyUGK5diRgABbAXgB0DSgSZEIQZcSBCsi8AiPibe3IUHxUUCD23X0DY8gTdspqGtoieomtk3ZLYCtrXT2904IF4shSyEr3fI804tu7JCFhCL2Jy+EDccT0MJ+AgTdLMZCOACqqE0+EmABFgHAmEoQNgvAAaSboaihIl2RzqbAQQmTAASVigYFpgWisXiAAUYgBPNyJZAQAAekDx8X582QXiowDA9CRKM4kwqVRqSjqA3oshKBMl0tlktB3DOC2IUtU0HqIzE2zstz6UplxnWdwqpGgYGcrjB2kcepEDrA1smf2Iqlc5EgUVxbqZnrcPr9AchhuNJq8AHcZQhOv69amTeVYigAESY7G4-HF2jnAskS7XBHIzS9Ms40U2k0IIvIYskqihKs12uLZarRso3p90IdhZdrwlylwaleQfDhb1sfy5uL5cz9pzksMrDM1dri6jtZb3pHplePd2anwKgUWVD2tdKBKdMMCDfgCiUCfnUQYFoEdghsgYbABGKCuu6voyj6hpzG+GZZjmdq9AG+a1ge47Nq2FZeNWZ7nlcY6llibaVvehbzvhk6ksRb4Fhuay9kxxa0Yo3ZXjuNIkaRxBsT2-ErtxUS8U216MsyglCSJxY3ieEmPnAz6vkJwkXj2XFvmBJAQQ4cZghCBpetwaKsTpJngphDyzGIRgANQ9m8MBua5mFwbGepIRZPzBjCQRsnEyAAFJKAA1tA-JCiK+IJNkVnlBYarJhZ2zKi41S1CIygUOl5luDhdhmhaACMAAsIEmt5aVQE6BVqr8QS2iCAViBlbgpeuNnIZhAwuW5xbIF5Gy9M1pRBRM2WSTgxFJTgADaAC6TprZwXYLb0qhUF4OYgL+yBcnAvJgokIgVTqlHlqKxZOVt2R9HtB0iEd36RTFUCXcWABCMQIFFD1iAQyoWBAvSFeC234stAAMq1BuDlhQ0oMPPQjq2TSo6hLEcsNeMtFVI8juJeBDaMYwtWO9MZyFOWD5OU9D+WYyTdMdW44ig8QQA)