| |

TypeScript for QA Engineers: The Essentials You Actually Need for Test Automation

You do not need to learn all of TypeScript to write Playwright tests. You need the 20% that covers 95% of test automation scenarios. Here are the essentials — nothing more, nothing less.

Contents

Types That Matter for Tests

// Basic types you will use daily
const testName: string = 'login flow';
const retryCount: number = 3;
const isEnabled: boolean = true;
const testIds: number[] = [1, 2, 3];

// Object types for test data
interface User {
  name: string;
  email: string;
  role: 'admin' | 'user' | 'guest'; // Union type = only these values
}

// Optional fields (common in API responses)
interface ApiResponse {
  id: number;
  data: User;
  error?: string;  // Optional — may or may not exist
}

Async/Await (The Most Important Concept)

// Every Playwright action is async
test('login flow', async ({ page }) => {
  await page.goto('/login');           // Wait for navigation
  await page.getByLabel('Email').fill('test@test.com');  // Wait for fill
  await page.getByRole('button', { name: 'Login' }).click(); // Wait for click
  await expect(page.getByText('Dashboard')).toBeVisible(); // Wait for assertion
});

// Common mistake: forgetting await
// page.goto('/login');  // BAD: does not wait, test continues immediately

Interfaces for Page Objects

// Type-safe Page Object
class LoginPage {
  constructor(private page: Page) {}

  async login(email: string, password: string): Promise<void> {
    await this.page.getByLabel('Email').fill(email);
    await this.page.getByLabel('Password').fill(password);
    await this.page.getByRole('button', { name: 'Login' }).click();
  }

  async getErrorMessage(): Promise<string> {
    return await this.page.getByRole('alert').textContent() ?? '';
  }
}

Generics for Reusable Utilities

// Generic API helper — works with any response type
async function apiGet<T>(request: APIRequestContext, path: string): Promise<T> {
  const response = await request.get(path);
  expect(response.ok()).toBeTruthy();
  return await response.json() as T;
}

// Usage — TypeScript knows the return type
const user = await apiGet<User>(request, '/api/users/1');
console.log(user.email); // TypeScript autocomplete works!

Enums for Test Configuration

enum Environment {
  Dev = 'https://dev.example.com',
  Staging = 'https://staging.example.com',
  Production = 'https://example.com',
}

enum UserRole {
  Admin = 'admin',
  User = 'user',
  Guest = 'guest',
}

// Type-safe configuration
const config = {
  baseUrl: Environment.Staging,
  defaultRole: UserRole.Admin,
};

What You Can Skip (For Now)

  • Decorators — rarely used in test code
  • Abstract classes — keep it simple with interfaces
  • Mapped types / conditional types — advanced and unnecessary for tests
  • Module declarations — Playwright handles this
  • Namespaces — use ES modules instead

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.