Design Pattern: Interpreter Pattern in TypeScript

Interpreter pattern is used to parse, represent, convert and/or implement some custom language/pattern. We can implement a custom interpreter using this pattern.

This article demonstrates Interpreter pattern implementation using TypeScript. Check the implementation details and examples.

Implementation

Here are the steps for Interpreter pattern implementation in TypeScript-

  • Create an interface that represents an operation. Make sure to declare a method for the main operation.
  • Create a class for terminal operation. Implement the interface for this class. In the main operation method implement the real checking/calculation.
  • Create a class for each operation and implement the operation interface for each class. In the main operation class, call the terminal operation and perform the specific operation on the result.

Examples

Here are a few examples of Interpreter pattern implementation in TypeScript-

Example #1: Logical Operation

In this example, we are representing some logical operations like AND, OR, XOR etc. in TypeScript using interpreter pattern.

Operation Interface

  • Create file “operation.ts”.
  • Create interface “Operation”.
  • Declare method “execute” that returns a boolean.
// operation.ts

interface Operation {
    execute(opContext: string): boolean
}

export default Operation;

Terminal Operation Class

  • Create file “terminal-operation.ts”.
  • Create class “TerminalOperation”.
  • In the constructor take a data param and save that in a class property.
  • Implement “Operation” interface for the class.
  • In the “execute” method check if the “data” contains the desired substring or not.
// terminal-operation.ts

import Operation from "./operation";

class TerminalOperation implements Operation {
    private data: string;

    constructor(data: string) {
        this.data = data;
    }

    execute(opContext: string): boolean {
        return opContext.includes(this.data);
    }
}

export default TerminalOperation;

AND Operation Class

  • Create file “and-operation.ts”.
  • Create class “AndOperation”.
  • Declare 2 private properties- “op1”, “op2”. These properties are of type “Operation”.
  • In the constructor accept and set the 2 properties.
  • Implement “Operation” interface for the class.
  • In the execution method call the execution method of “op1” and “op2”, then perform a “AND” (&&) operation on those results.
// and-operation.ts

import Operation from "./operation";

class AndOperation implements Operation {
    private op1: Operation;
    private op2: Operation;

    constructor(op1: Operation, op2: Operation) {
        this.op1 = op1;
        this.op2 = op2;
    }

    execute(opContext: string): boolean {
        return this.op1.execute(opContext) && this.op2.execute(opContext);
    }
}

export default AndOperation;

OR Operation Class

  • Create file “or-operation.ts”.
  • Create class “OrOperation”.
  • Declare 2 private properties- “op1”, “op2”. These properties are of type “Operation”.
  • In the constructor accept 2 Operatnios and set the properties.
  • Implement “Operation” interface for the class.
  • In the execution method call the execution method of “op1” and “op2”, then perform a “OR” (||) operation on those results.
// or-operation.ts

import Operation from "./operation";

class OrOperation implements Operation {
    private op1: Operation;
    private op2: Operation;
    constructor(op1: Operation, op2: Operation) {
        this.op1 = op1;
        this.op2 = op2;
    }

    execute(opContext: string): boolean {
        return this.op1.execute(opContext) || this.op2.execute(opContext);
    }
}

export default OrOperation;

XOR Operation Class

  • Create file “xor-operation.ts”.
  • Create class “XorOperation”.
  • Declare 2 private properties- “op1”, “op2”. These properties are of type “Operation”.
  • In the constructor accept 2 Operations and set the properties.
  • Implement “Operation” interface.
  • In the execution method call the execution method of “op1” and “op2”, then perform a “XOR” (which is equivalent to “!=” in this case) operation on those results.
// xor-operation.ts

import Operation from "./operation";

class XorOperation implements Operation {
    private op1: Operation;
    private op2: Operation;

    constructor(op1: Operation, op2: Operation) {
        this.op1 = op1;
        this.op2 = op2;
    }

    execute(opContext: string): boolean {
        return this.op1.execute(opContext) != this.op2.execute(opContext);
    }
}

export default XorOperation;

Demo

For using the implementation, create 2 TerminalOpration objects, named “op1” and “op2”. Here we are using 2 strings “Big” and “Box”, as we want to perform the operations to check both these operations exist in some strings and perform AND/OR/XOR operations on those.

Then we created objects for “AndOpeation”, “OrOperation”, and “XorOperation”, and also passed “op1”, “op2” to those.

Later we have some full strings for the check. We can call the AndOperation/OrOperation/XorOperation object “execute” method and pass the check string for the main checking.

// demo.ts

import AndOperation from "./and-operation";
import OrOperation from "./or-operation";
import TerminalOperation from "./terminal-operation";
import XorOperation from "./xor-operation";

const op1 = new TerminalOperation("Big");
const op2 = new TerminalOperation("Box");

const andChecker = new AndOperation(op1, op2);
const orChecker = new OrOperation(op1, op2);
const xorChecker = new XorOperation(op1, op2);

const checkStr1 = "Big Box Code";
const checkStr2 = "Only Big Code";
const checkStr3 = "Only Box Code";
const checkStr4 = "No Code";

const andResult1 = andChecker.execute(checkStr1);
const andResult2 = andChecker.execute(checkStr2);
const andResult3 = andChecker.execute(checkStr3);
const andResult4 = andChecker.execute(checkStr4);

console.log("Data: " + checkStr1 + "; AND Result: " + andResult1);
console.log("Data: " + checkStr2 + "; AND Result: " + andResult2);
console.log("Data: " + checkStr3 + "; AND Result: " + andResult3);
console.log("Data: " + checkStr4 + "; AND Result: " + andResult4);

const orResult1 = orChecker.execute(checkStr1);
const orResult2 = orChecker.execute(checkStr2);
const orResult3 = orChecker.execute(checkStr3);
const orResult4 = orChecker.execute(checkStr4);

console.log("Data: " + checkStr1 + "; OR Result: " + orResult1);
console.log("Data: " + checkStr2 + "; OR Result: " + orResult2);
console.log("Data: " + checkStr3 + "; OR Result: " + orResult3);
console.log("Data: " + checkStr4 + "; OR Result: " + orResult4);

const xorResult1 = xorChecker.execute(checkStr1);
const xorResult2 = xorChecker.execute(checkStr2);
const xorResult3 = xorChecker.execute(checkStr3);
const xorResult4 = xorChecker.execute(checkStr4);

console.log("Data: " + checkStr1 + "; XOR Result: " + xorResult1);
console.log("Data: " + checkStr2 + "; XOR Result: " + xorResult2);
console.log("Data: " + checkStr3 + "; XOR Result: " + xorResult3);
console.log("Data: " + checkStr4 + "; XOR Result: " + xorResult4);

Output

The output will be as below-

Data: Big Box Code; AND Result: true
Data: Only Big Code; AND Result: false
Data: Only Box Code; AND Result: false
Data: No Code; AND Result: false

Data: Big Box Code; OR Result: true
Data: Only Big Code; OR Result: true
Data: Only Box Code; OR Result: true
Data: No Code; OR Result: false

Data: Big Box Code; XOR Result: false
Data: Only Big Code; XOR Result: true
Data: Only Box Code; XOR Result: true
Data: No Code; XOR Result: false

Source Code

Use the following link to get the source code:

Other Code Implementations

Use the following links to check Interpreter pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.