Typing Speed Detector App Using Typescript
Last Updated :
05 Feb, 2025
Improve
Typing speed has been a very important test for Engineers as a faster typing skill leads to faster code so, To test this speed we are building a typing speed detector.
What We’re Going to Create
- An Input Box for Typing Our Text.
- A Time Element to show the time.
- An Element to show Words per minute.
- A start Button to start the test.
Project Preview

Typing Speed Detector - HTML and CSS code
This is a Typing Speed Test web app where users can measure their typing speed in Words Per Minute (WPM). It includes a timer, input area, and a start button to begin the test.
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
flex-direction: column;
}
.box {
text-align: center;
background: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 400px;
}
h1 {
font-size: 24px;
margin-bottom: 20px;
}
#txt {
font-size: 18px;
margin-bottom: 20px;
font-weight: bold;
}
#inp {
width: 100%;
height: 100px;
font-size: 16px;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ccc;
border-radius: 5px;
resize: none;
}
.stats {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
button {
padding: 10px 20px;
background: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:disabled {
background: #ccc;
}
button:hover {
background: #45a049;
}
</style>
</head>
<body>
<div class="box">
<h1>Typing Speed Test</h1>
<p id="txt">Press Start to begin typing</p>
<textarea id="inp" placeholder="Start typing here..." disabled></textarea>
<div class="stats">
<p id="tm">Time: 0s</p>
<p id="wpm">WPM: 0</p>
<button id="start">Start</button>
</div>
</div>
<script defer src="typing.js"></script>
</body>
</html>
In this Example
- A centered .box container with a clean design, including a heading, sentence display, text input, and stats section.
- The #inp textarea is disabled initially and gets activated when the user clicks the Start button (#start).
- The #tm (Time) and #wpm (Words Per Minute) update in real time as the user types, tracking their typing speed.
Typing Speed Detector - Typescript logic
This code creates a dynamic grid that allows users to draw on it by changing the grid size and color. It supports interaction with mouse events for drawing and resetting the grid.
const c = document.querySelector<HTMLDivElement>(".container");
const s = document.querySelector<HTMLInputElement>('.size');
const col = document.querySelector<HTMLInputElement>('.color');
const rBtn = document.querySelector<HTMLButtonElement>('.button');
if (!c || !s || !col || !rBtn) {
throw new Error("Missing required DOM elements");
}
let sz: number = parseInt(s.value);
let d: boolean = false;
function g(): void {
c.style.setProperty("--size", sz.toString());
c.innerHTML = "";
for (let i = 0; i < sz * sz; i++) {
const b = document.createElement("div");
b.classList.add("box");
b.addEventListener('mouseenter', () => o(b));
b.addEventListener('mousedown', () => m(b));
c.appendChild(b);
}
}
function o(b: HTMLDivElement): void {
if (!d) return;
b.style.backgroundColor = col.value;
}
function m(b: HTMLDivElement): void {
b.style.backgroundColor = col.value;
}
window.addEventListener('mousedown', () => {
d = true;
});
window.addEventListener('mouseup', () => {
d = false;
});
function r(): void {
g();
}
rBtn.addEventListener('click', r);
s.addEventListener('change', () => {
sz = parseInt(s.value);
r();
});
g();
In this example
- The g() function generates a grid of sz × sz cells, clearing the previous grid before adding new ones.
- The grid size updates dynamically based on user input (.size input field).
- Cells change color (col.value) when hovered over (mouseenter) or clicked (mousedown).
- A boolean d tracks whether the mouse is pressed, allowing smooth drawing.
- Clicking the Reset button (.button) clears and recreates the grid.
- It ensures users can start over without reloading the page.
- When the user changes the .size input, the s.addEventListener('change', ...) triggers a new grid update.
Convert to JavaScript File
Now You need to convert the TypeScript file into JavaScript to render by browser. Use one of the following command.
npx tsc typing.ts
tsc typing.ts
- The command typing.ts compiles the typing.ts TypeScript file into a typing.js JavaScript file.
- It places the output in the same directory as the input file by default.
Complete Code
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
flex-direction: column;
}
.box {
text-align: center;
background: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 400px;
}
h1 {
font-size: 24px;
margin-bottom: 20px;
}
#txt {
font-size: 18px;
margin-bottom: 20px;
font-weight: bold;
}
#inp {
width: 100%;
height: 100px;
font-size: 16px;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ccc;
border-radius: 5px;
resize: none;
}
.stats {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
button {
padding: 10px 20px;
background: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:disabled {
background: #ccc;
}
button:hover {
background: #45a049;
}
</style>
</head>
<body>
<div class="box">
<h1>Typing Speed Test</h1>
<p id="txt">Press Start to begin typing</p>
<textarea id="inp" placeholder="Start typing here..." disabled></textarea>
<div class="stats">
<p id="tm">Time: 0s</p>
<p id="wpm">WPM: 0</p>
<button id="start">Start</button>
</div>
</div>
<script defer>
const txt = document.getElementById("txt");
const inp = document.getElementById("inp");
const tm = document.getElementById("tm");
const wpm = document.getElementById("wpm");
const startBtn = document.getElementById("start");
let time = 0;
let timer = null;
let isRunning = false;
const sampleText = "The quick brown fox jumps over the lazy dog"; // Sample sentence
function startTest() {
clearInterval(timer);
isRunning = true;
time = 0;
tm.textContent = "Time: 0s";
wpm.textContent = "WPM: 0";
inp.value = "";
inp.disabled = false;
inp.focus();
txt.textContent = sampleText;
timer = setInterval(() => {
time++;
tm.textContent = `Time: ${time}s`;
calculateWPM();
}, 1000);
}
function calculateWPM() {
let wordsTyped = inp.value.trim().split(/\s+/).length;
let wordsPerMinute = time > 0 ? Math.round((wordsTyped / time) * 60) : 0;
wpm.textContent = `WPM: ${wordsPerMinute}`;
}
inp.addEventListener("input", () => {
calculateWPM();
if (inp.value.toLowerCase().replace(/\s+/g, " ")
.trim() === sampleText.toLowerCase().replace(/\s+/g, " ").trim()) {
clearInterval(timer);
isRunning = false;
inp.disabled = true;
wpm.textContent = `WPM: ${Math.round((sampleText.split(" ")
.length / time) * 60)}`;
alert(`Test Completed! Your WPM: ${wpm.textContent.split(" ")[1]}`);
}
});
startBtn.addEventListener("click", startTest);
</script>
</body>
</html>