You are the best software engineer in the world. Please convert the following Python code into Node.js TypeScript.

```
import numpy as np
import json
import time
import threading
import keyboard
import sys
from mss import mss as mss_module
from PIL import Image

HORIZONTAL_LEN, VERTICAL_LEN = [1920, 1080]

SCAN_RADIUS = 3
CENTER_CROP_AREA = (
    int(HORIZONTAL_LEN / 2 - SCAN_RADIUS),
    int(VERTICAL_LEN / 2 - SCAN_RADIUS),
    int(HORIZONTAL_LEN / 2 + SCAN_RADIUS),
    int(VERTICAL_LEN / 2 + SCAN_RADIUS),
)


def quit_app():
    try:
        sys.exit()
    except:
        raise SystemExit
    

class App:
    def __init__(self):
        self.scrcpy = mss_module()
        self.is_active = False
        self.is_toggle = True
        self.exit_app = False
        self.thread_lock = threading.Lock()
        self.wasd_pressed = False
        self.last_wasd_release_time = time.time()

        with open('config.json') as json_file:
            data = json.load(json_file)

        try:
            self.hotkey = int(data["triggerhotkey"], 16)
            self.always_enabled = data["alwaysenabled"]
            self.trigger_delay = data["triggerdelay"]
            self.base_delay = data["basedelay"]
            self.tolerance = data["colortolerance"]
            self.firekey = data["firekey"]
            self.R, self.G, self.B = (250, 100, 250)
        except:
            quit_app()
        print("Started!")

    def wait(self):
        time.sleep(0.1)
        with self.thread_lock:
            self.is_toggle = True

    def scan(self):
        # if self.wasd_pressed:
        #    return

        img = np.array(self.scrcpy.grab(CENTER_CROP_AREA))
        
        pmap = np.array(img)
        px = pmap.reshape(-1, 4)
        color_mask = (
            (px[:, 0] > self.R - self.tolerance) & (px[:, 0] < self.R + self.tolerance) &
            (px[:, 1] > self.G - self.tolerance) & (px[:, 1] < self.G + self.tolerance) &
            (px[:, 2] > self.B - self.tolerance) & (px[:, 2] < self.B + self.tolerance)
        )
        matching_pixels = px[color_mask]
        
        if self.is_active and len(matching_pixels) > 0:
            delay_percentage = self.trigger_delay / 100.0
            actual_delay = self.base_delay + self.base_delay * delay_percentage
            time.sleep(actual_delay)
            keyboard.press(self.firekey)
            time.sleep(0.12)
            keyboard.release(self.firekey)
            time.sleep(0.4)

    def on_toggle(self):
        if keyboard.is_pressed("f10"):  
            # Save image
            im = np.array(self.scrcpy.grab(CENTER_CROP_AREA))
            im = Image.fromarray(im).convert('RGB')
            im.save("screenshot.jpg")
            
            with self.thread_lock:
                if self.is_toggle:
                    self.is_active = not self.is_active
                    print(self.is_active)
                    
                    self.is_toggle = False
                    threading.Thread(target=self.wait).start()

        if keyboard.is_pressed("ctrl+shift+x"):
            self.exit_app = True
            quit_app()

    def check_mv(self):
        if keyboard.is_pressed('w') or keyboard.is_pressed('a') or keyboard.is_pressed('s') or keyboard.is_pressed('d'):
            self.wasd_pressed = True
        else:
            if self.wasd_pressed:
                self.last_wasd_release_time = time.time()
            self.wasd_pressed = False

    def letsgo(self):
        while not self.exit_app:
            # self.check_wasd()
            if self.always_enabled == True:
                self.on_toggle()
            self.scan() if self.is_active else time.sleep(0.1)

if __name__ == "__main__":
    try:
        App().letsgo()
    except KeyboardInterrupt:
        print("Quit!")
        quit_app()
```