# 🗺️ Your First Steps in TypeScript: A Practical Roadmap for Automation QA

Ever had a test fail at a critical moment due to a simple typo in a variable or an unexpected API response? We’ve all been there. These runtime errors are frustrating and time-consuming. This is where TypeScript comes in.

For QA Testers, TypeScript is more than just a programming language - it’s a safety net. It helps you catch bugs before you run your tests, not during. This article is your starting point. We'll cover the **essentials** you need to start writing more robust and reliable automated tests today.

---

### ✅ Prerequisites

While experience with **JavaScript, Playwright, or Cypress** is beneficial, it’s not required. We’ll explain everything in a simple way, making this a great starting point even for beginners.

---

### 🤔 The “Why”: Catching Bugs Before They Happen

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1749724896357/859c2127-63dd-4bc9-a87d-6a93d96ed5ed.jpeg align="center")

Imagine you're testing an API. You expect a response body with a user's `id` and `username`. In JavaScript, you might write a test like this:

```js
const userId = response.body.id;
const userPassword = response.body.password; // Oops!
```

Your test would run, and only then would it fail because `response.body.password` is undefined. It’s a bug in your code, but you only found it at runtime.

With TypeScript, you would first define the shape of your expected data. If you tried to access `.password`—a key that doesn't exist in your defined shape—TypeScript would show an error right in your code editor. **You fix the bug before the test even runs**. This is the core power of TypeScript: **adding confidence and preventing errors.**

---

### 🧱 The Building Blocks: Core Types

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1utts72p5k1gkonre0j3.jpg align="left")

At its heart, TypeScript is about adding type annotations to your variables. Think of it as giving every variable a specific job description.

A `string` is used for text data, like URLs, locators, or messages.

```ts
const blogURL: string = 'https://idavidov.eu/';
```

In testing, you'll use strings constantly for base URLs, selectors, and test data. Typing them ensures you don't accidentally try to perform a mathematical operation on a URL!

A `number` is for, well, numbers! This includes integers and decimals.

```ts
const expectedItemCount: number = 13;
```

This is perfect for asserting an expected element count, checking API status codes (200, 404), or verifying prices.

A `boolean` can only be `true` or `false`. It’s the ultimate "yes or no."

```ts
const isButtonEnabled: boolean = true;
```

Booleans are essential for checking the state of UI elements. Is a checkbox ticked? Is a button visible? Is a toggle on? A boolean gives you a clear answer.

---

### ✍️ Building Dynamic Strings with Template Literals

Hardcoding strings is rarely practical. You often need to build them dynamically. Template literals make this clean and easy. You use backticks instead of quotes and embed variables with `${...}`.

```ts
const blogURL: string = 'https://idavidov.eu/';

// Dynamically create a new URL
const newsletterURL: string = `${blogURL}newsletter`;

console.log(newsletterURL); // Outputs: 'https://idavidov.eu/newsletter'
```

This is incredibly useful for QA work, such as building API endpoints with dynamic IDs or creating detailed assertion messages that include variable outputs.

### ✨ The Special Trio: `void`, `any`, and `unknown`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1749724973501/f3b53346-5d76-40c9-bcfb-a279b00d13ce.jpeg align="center")

Beyond the basics, **TypeScript** has special types for unique situations.

#### `void`: For Actions, Not Data

What about functions that do something but don't return a value? Think of a function that clicks an element. Its job is to perform an action, not to give you data back. This is what void is for.

```ts
// This helper performs a click but doesn't return anything.
function clickElement(selector: string): void {
  // In a real Playwright/Cypress test, you'd have:
  // await page.click(selector);
  console.log(`Successfully clicked on ${selector}!`);
}
```

Using `void` makes your code clearer. It tells other developers (and your future self) that the function's purpose is its side effect, not its return value.

#### `any`: The Double-Edged Sword 🗡️

Sometimes, you might be working with legacy JavaScript code or a poorly documented library. In these cases, you can use `any` as an "escape hatch." It effectively tells TypeScript, "Don't type-check this variable."

```ts
// Use with extreme caution!
let legacyData: any = { "user-id": 123, details: "some-info" };

// TypeScript won't complain about this, even if it's wrong.
console.log(legacyData.nonExistentProperty); // Returns 'undefined' at runtime
```

**The Risk:** Using `any` completely defeats the purpose of TypeScript. It hides potential bugs and should be used as a last resort. Always aim to replace `any` with a proper type as soon as you can.

#### `unknown`: The Safe Alternative 🛡️

So what if you truly don't know the type of data you're getting, like from an external API? Use `unknown`. It's the type-safe version of `any`.

`unknown` forces you to check the type of the data before you're allowed to do anything with it.

```ts
async function fetchUserData(userId: number): Promise<void> {
  const response = await fetch(`https://api.example.com/users/${userId}`);
  const data: unknown = await response.json();

  // We MUST check the type before using it
  if (
    typeof data === 'object' &&
    data !== null &&
    'name' in data &&
    typeof data.name === 'string'
  ) {
    // Only inside this block does TypeScript know data has a 'name' property
    console.log(`User's name is ${data.name.toUpperCase()}`);
  } else {
    console.error("API response is not in the expected format.");
  }
}
```

`unknown` is perfect for QA because it forces us to write defensive code that can safely handle unexpected API responses without crashing.

### 🚀 Your Next Step

We've covered the absolute essentials for getting started with TypeScript in a QA role. From basic types that clarify your intent to special types that help you handle tricky situations safely.

The single most important message is this: **TypeScript isn't about adding complexity; it's about adding confidence.** You can trust your tests more because an entire category of bugs is eliminated before you ever run them.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1749725032625/0237d9da-55e0-46e8-8923-bd39ef30d7f2.jpeg align="center")

Your immediate next step? Go and convert one of your small JavaScript test files to TypeScript. Add types to your variables (`.ts` file extension) and see what potential issues you uncover. You might be surprised by what you find!

---

> **🙏🏻 Thank you for reading!** Building robust, scalable automation frameworks is a journey best taken together. If you found this article helpful, consider joining a growing community of QA professionals 🚀 who are passionate about mastering modern testing.

> [Join the community and get the latest articles and tips by signing up for the newsletter.](https://idavidov.eu/newsletter)
