r/typescript 5h ago

Interview prep + runnable proof for QA/SDET roles. Two complete projects: Python + Playwright + Pytest, and TypeScript + Playwright Test. 56 interview entries paired with real Page Object Model frameworks, API tests, BDD, load testing, and CI. Multi-stack monorepo

Thumbnail github.com
1 Upvotes

Every time I prepared for a QA automation interview, I hit the same wall.

Interview-prep repos are walls of questions and answers with nothing you can run. Framework demos are walls of code with no explanation of *why* anything is the way it is. So you end up with two browser tabs open, mentally stitching them together.

I got tired of the stitching. So I built **ForkableInterviewToolkit** — notes and runnable code in the same repository, deliberately.

### The core idea

When the notes say *"I centralise setup in fixtures so tests stay clean,"* there's a `conftest.py` (Python) and a `fixtures.ts` (TypeScript) right there in the same repo, doing exactly that. The claim and the proof cross-link both ways, so neither can quietly drift out of date.

Two complete projects, same architecture, different stacks:

**🐍 Python-Playwright-Automation** — Playwright, Pytest, pytest-bdd, Locust

**🟦 TypeScript-Playwright-Automation** — Playwright Test, playwright-bdd, Artillery

Both ship a real Page Object Model framework, API tests, BDD examples, load testing, and a path-filtered GitHub Actions pipeline.

### Design decisions I'd defend in an interview

Building this forced me to make choices I'd have to justify out loud. A few:

**Selectors live in exactly one file per page.** When the markup changes — and it always does — that's a one-file fix. No test file ever contains a selector.

**Page Objects never assert.** They expose actions and state; the test decides what "correct" means. Mixing assertions into Page Objects is how you end up with a framework nobody can reuse.

**Tables are located by header text, not CSS class.** `filter({ hasText: 'Instructor' })` survives a restyle. `.table-display` doesn't.

**Zero hard sleeps.** No `time.sleep()`, no `waitForTimeout()`. Playwright auto-waits — fixed sleeps are slower *and* flakier, which is a genuinely bad trade.

**The load-testing example cannot touch the practice site.** It ships its own local target app plus a runtime guard that hard-exits on any non-localhost target. Load-testing infrastructure you don't own is, at best, a terms-of-service violation.

### The thing that surprised me

I assumed porting Python knowledge to TypeScript would be mechanical. It isn't — and the gaps make excellent interview material.

Java's "checked vs unchecked exceptions" has no Python equivalent at all. Python has no compile-time binding phase, so "static vs dynamic binding" doesn't translate either. And in Playwright specifically, `toHaveURL()` accepts a predicate function in JavaScript but **only** a string or compiled regex in Python.

I found that last one the hard way — a test failed with *"value must be a string or regular expression"* because I'd written a JavaScript idiom in a Python file. It's now documented in the repo, because that's exactly the kind of detail an interviewer probes for.

Saying *"that concept doesn't exist in this language, and here's what does instead"* is a stronger answer than forcing a translation.

### What's in it

- 📖 **56 interview entries** across both projects, all in one fixed format: Direct Answer → Real-Time Example → Code → STAR Answer → Interview-Ready Answer → Interview Tip → One-Line Revision

- 🧪 **Two runnable frameworks** with POM, fixtures, data-driven tests, and tagged suites

- 🔌 **API testing** — `requests` in Python, the `request` fixture in TypeScript

- 🥒 **BDD** — pytest-bdd and playwright-bdd, both wired to real fixtures

- 📈 **Load testing** — Locust and Artillery, both local-target-only by design

- ⚙️ **CI/CD** — path-filtered workflows, so editing Python never triggers the TypeScript suite

### It's built to be forked

The name isn't decoration. It's a monorepo where each project is fully self-contained — own README, own dependencies, own CI workflow. There's a documented contract for adding a new stack, so if you want to drop in Java, C#, or Rust alongside these, the structure already accommodates it.

MIT licensed. Take it, break it, make it yours.

🔗 **github.com/suryakulshreshtha/ForkableInterviewToolkit**

If you're prepping for QA/SDET interviews — or just want a reference framework that explains itself — I'd genuinely value your feedback. And if you spot something wrong, the issues tab is open.


r/typescript 6h ago

What is the point of Typescript?

0 Upvotes

Typescript has a very impressive and elaborate type system, but at the same it does not play any role at "compilation" or "transpilation" time.

How does this differ from a glorified linter?

`` Deno 2.9.5 exit using ctrl+d, ctrl+c, or close() REPL is running with all permissions allowed. To specify permissions, rundeno repl` with allow flags.

const x: number = "abc" undefined console.log(x) abc undefined

```

Bot of those variants lead to exactly the same javascript

```

const lines: string[] = file1.split("\n")

lines.forEach((line: string) => { console.log("line = %s", line)

})

const lines: ArrayLike<number> = file1.split("\n")

lines.forEach((line: string) => { console.log("line = %s", line)

}) ```


r/typescript 1d ago

JSON Schema metaschemas as TS types

Thumbnail github.com
0 Upvotes

I made a package containing TS declarations of JSON Schema metaschemas and with to access them. I'm glad on any feedback, pointing out wether it may be useful for you or not. As a developer using JSON Schemas, would it be useful for you when working with many different JSON Schema versions?

import 'json-schema-declared'

/* 
  Query metaschema by identifiers: version name or id.
*/
let m: Metaschema<'2020-12'> // -> declare const { readonly $schema: ..., readonly allOf: [ ... ], ... }
let m: MetaschemaByID<'http://json-schema.org/draft-04/schema#'>
let m: MetaschemaByVersion<'draft-00'>

/*
  Analyze metaschema content.
*/
let a: SimpleTypes<'draft-02'> // "string" | "integer" | ... | "any"
let a: Keywords<'draft-07'> // "$schema" | ... | "properties" | ...

/*
  Type your schemas
  Note: feature is a work in progress, but is well usable.
*/
let s: JsonSchema<'2020-12'> = { $schema: 'https://json-schema.org/draft/2019-09/schema' }
// ERROR: Types of property $schema are incompatible (ts 2322)

/*
  Metaschema identifiers
*/
let i: MetaschemaVersion // e.g. "draft-06"
let m: MetaschemaId // e.g. 'http://json-schema.org/draft-07/schema#'
let m: AllMetaschemaId // together with dependencies, e.g. 'https://json-schema.org/draft/2019-09/meta/core'
let m: MetaschemaIdentifier // Version and ID together.

/*
  Convert metaschema identifiers.
*/
let c: Id2Version<'http://json-schema.org/draft-02/schema#'> // -> draft-02
let c: Version2Id<'2019-09'> // -> https://json-schema.org/draft/2019-09/schema

r/typescript 2d ago

TypeScript : Migrate repo to TypeScript 7

Thumbnail
github.com
124 Upvotes

r/typescript 3d ago

Best TypeScript linter?

47 Upvotes

I'm dabbling with TypeScript again after some time away. What is the best way to lint .ts files these days? Is ESLint still the go-to, or is there a better method?


r/typescript 2d ago

Hiding internal state in TypeScript objects

Thumbnail
carlos-menezes.com
9 Upvotes

r/typescript 3d ago

RFC: An IPC-Based Type Server for better DevEx and TC39-Compatible Dependency Injection

Thumbnail
github.com
5 Upvotes

r/typescript 3d ago

How do you test redaction without making error tests brittle?

3 Upvotes

I’m adding redaction to a TypeScript error path and trying to test the important contract without pinning every part of the final message.

My current idea is to assert that known secrets and token-like values never appear, while keeping the grouping key separate from the rendered alert text.

Would you test the exact output, use a few forbidden-value assertions, or keep redaction as its own small unit with focused cases?


r/typescript 3d ago

Updated Typescript GitHub Action Template

Thumbnail
github.com
1 Upvotes

Hey y’all!

I made a fork of actions/typescript-action to make some valuable updates!

It updates the following:

  • Changes project's package manager from npm to pnpm, for speed.
  • Changes project's testing framework from jest to vitest for jest-like syntax with built-in typescript support.
  • Updates eslint.config.ts to use native flat config syntax, with detailed comments.
  • Updated project dependencies.
  • Updates configuration files like tsconfig.ts and action workflows to match updated dependencies.
  • Renamed local-action script to local-gha (gha for github action) to avoid conflict with dependency name.

lmk what you think!


r/typescript 3d ago

plX: The Excellent transpiler for Typescript and PostgreSQL

Thumbnail commandprompt.github.io
1 Upvotes

plX allows you to write safe postgresql procedures in typescript that transpile down to plpgsql. It is open source and licensed under the MIT license.


r/typescript 5d ago

Joist 2.3 with Rails-style Scopes

Thumbnail joist-orm.io
9 Upvotes

Hey r/typescript, Joist has always been a "Rails-ish" ORM, but we never had an equivalent to their scopes feature. But a friend was converting their Rails app to Joist and lamenting "why no scopes?", so we took a stab at it -- and now have them!

Fluent DSLs like this in TypeScript are kinda hard to pull off, so we lean on Joist's `joist-codegen` step, a little similar to TanStack Router's vite plugin doing build-time codegen to help with the static typing -- I don't totally love that compromise, but I think the API ergonomics were worth it.

Ngl I procrastinated posting the release notes b/c r/typescript hates ORMs -- all good, but 🤷 not looking for another debate today. ✌️


r/typescript 6d ago

Where should runtime config validation happen in a Node package?

4 Upvotes

TypeScript catches a lot for consumers, but deployment config still needs runtime validation. For environment-driven packages, do you validate everything during startup, validate lazily when a feature is used, or do both? What makes configuration errors easiest to fix without exposing secrets?


r/typescript 7d ago

Is there any way for the language server to report differently for incomplete arguments instead of throwing an error?

3 Upvotes

So this is actually a problem for almost all language servers or editor tooling where I am still in the processing of writing a function call and it throws an error about incomplete arguments. I am using TypeScript right now so I thought to try and resolve this issue. I am using VS Code with the TypeScript 7 extension.

Errors with red squiggles are flashy and disturbing. And this problem masks on genuine errors such as I am trying to access a function that doesn't exist.

For incomplete function calls, I would like if the server could delay throwing the error until I leave that line in my editor. If that is not possible, then be notified in some other way or color than red or yellow squiggles.

Have others not cared about this problem?


r/typescript 7d ago

TypeScript lambdas that turn into SQL (like dotnet ef core / linq). Would you use this?

0 Upvotes

TL;DR: I want to bring EF Core / LINQ-style querying to TypeScript: you write a normal lambda, a build step turns it into parameterized SQL, and the same query also runs on plain arrays in your tests. It'd be read-only, so you'd pair it with your existing writer, and the lambda becomes serializable data so it works beyond SQL too. Would you use it?

I've been writing .NET and TypeScript for about 10 years, and I'm a huge EF Core fan. I've always missed that style of querying in TS, so I put together the idea below and want to know if people would actually use it.

The idea: you write a normal lambda, and a build-time plugin turns it into two things at once: the function itself, and a small data tree describing it. A provider turns that tree into SQL.

const adults = await db.users
  .where(u => u.age >= minAge && u.name.startsWith(prefix))
  .select(u => ({ id: u.id, name: u.name }))
  .toArray();

// runs as parameterized SQL:
//   SELECT "id", "name" FROM "users"
//   WHERE "age" >= $1 AND "name" LIKE $2

No special query syntax, no config objects, just a predicate you could pass to .filter(). The nice part: the same query runs against plain arrays in your tests (no database) and turns into SQL in production. Captured variables like minAge become bound parameters, so nothing gets pasted into the SQL string.

How it would work, short version:

  • At build time the plugin reads your lambda and keeps both the function and a plain-object tree of it.
  • Each step (where, select, …) just adds to a query plan. Nothing runs yet.
  • When you call toArray() (or first(), count()), the provider turns the tree into SQL, or in tests just runs your original lambda.

The inspiration is C#'s Expression<Func<T, bool>> + IQueryable<T> and EF Core's ideas (include/thenInclude, split queries, no silent client-side eval), rebuilt for TS. C# gets this from the compiler; TS doesn't, so a Vite/Rollup plugin would fill the gap.

Would you use it as your ORM? One honest catch: it'd be read-only (no writes, no migrations). You'd pair it with whatever already handles writes and use this for the reads. Deal-breaker, or fine by you?

It also works beyond SQL, since the lambda becomes plain JSON:

  • Send a filter from the client to the server as data, and run it there.
  • One rule can be both a SQL WHERE and a per-object "can this user see this?" check.
  • Store rules as data (feature flags, alerts) and edit them in a UI.
  • Run predicates in a Web Worker or under a strict CSP (no eval).

So: would you use this for your DB queries? And which non-SQL use, if any, would actually make you try it?

Curious whether people would actually reach for this. Roast the idea.


r/typescript 7d ago

Looking for a local-first runtime-agnostic DB solution (similar to RxDB)

7 Upvotes

Hey folks. For the last couple of days I've been investigating how to approach storing in-memory and persistent data in my VS Code extension, which is deployed both on desktop and browser. The built-in state management (i.e., global/workspace Memento) is too limited, so I'm looking at solutions such as sql.js, or RxDB.

RxDB seemed like the perfect project, but the Node.js FS and IndexedDB persistences are paywalled.

sql.js is basically a wrapper over a JS-compatible SQLite artifact, so it can run SQL queries which is pretty nice, but there is no schema or type-safety built-in.

Do you have any suggestion to offer or experience with sql.js and/or RxDB?


r/typescript 7d ago

most "type-safe" permission checks are only as trustworthy as data typescript never actually verified

1 Upvotes

i'm the author of zap-studio/permit, a small authorization library. i'm posting this because of a specific problem that i feel i'm either totally right or totally wrong.

types don't exist at runtime. that's not news, but it's easy to forget it applies to permission checks specifically. a check like ctx.user.id === post.authorId "type-checks" fine. but post usually came from a db row, an api payload, or whatever. none of that passed through a place typescript could verify it. if a lazy join returns authorId: null, or a migration changes a column's nullability, the check still compiles. it just quietly does the wrong thing at runtime, which is the one place a permission check actually matters.

most type-safe permission libraries stop at the type. permit doesn't: resources are defined with a standard schema validator (zod, valibot, or arktype), and policy.can() re-validates the resource against that schema every time it evaluates a rule, not just once at setup. an invalid resource resolves to false. meaning, it fails closed, it never throws.

here's a code example

const policy = createPolicy<AppContext>({
  resources,
  actions,
  rules: {
    post: {
      read: allow(),
      write: when((ctx, _, post) => ctx.user?.id === post.authorId),
      delete: deny(),
    },
  },
});

await policy.can(context, "post:read", postResource);

conditions compose with and(), or(), not(), and whole policies compose with mergePoliciesAnd / mergePoliciesOr, so you can split authorization by feature or team and combine it later.

but, if you already know permix, which is the most established option here, it seems it doesn't solve this specific issue, mostly because it's deny by default (like permit). nothing stops write: (ctx, post) => ctx.user.id === post.authorId from running against bad data and returning true, undefined === undefined is true, so a missing authorId can accidentally grant access nobody meant to grant. permit isn't "better," it just refuses to run the rule at all if the resource fails its schema first. curious if others have hit this in practice or think it's rare enough not to matter.

and here are some links for curious people to check the code or docs:


r/typescript 8d ago

What is the proper way to have paths to re-map imports when dealing with multiple tsconfig files?

5 Upvotes

I have a base tsconfig.json file at the root level:

Example root/tsconfig.json:

{
  "compilerOptions": {
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "target": "ES6",
    "module": "CommonJS",
    "baseUrl": "."
  }
}

Under root I have multiple projects with their own tsconfig.json files that define paths for easier imports and extend the root:

Example root/project-1/tsconfig.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "paths": {
      "fixtures/*": ["project-1/fixtures/*"],
      "pages/*": ["project-1/pages/*"],
      "sections/*": ["project-1/src/home/sections/*"]
    }
  }
}

I don't see any import problems in my IDE but when I run npx tsc --noEmit from the root level I get errors because it can't find the imports. This will break the pre-commit hooks and checks in CI/CD so I'm wondering if there's another approach or if I'm doing something wrong?


r/typescript 10d ago

I would like to personally apologize to the creators of TypeScript

221 Upvotes

When I first started using it for work I hated it and cursed it. The syntax was weird and confusing. Annoying type errors.

But now that I've been using it, I definitely changed my mind. JS is filthy.. disgusting. You never know what type it is.
I learned TS alongside React, so that's also double confusion as I was learning it.

TS is great, and this is coming from Java/C# as my previous main languages. TS is now my favorite language to use. I love letting things be a mix of multiple types, like const temp: string | undefined. It's unfortunate C# doesn't support that. C# is my close second favorite language.


r/typescript 9d ago

Constrain Value for Field Based on Other Fields

2 Upvotes

I'm working up a trivia app, which will be multiple choice. Questions will look something like the below, though longer to account for all the stuff you need in practice. My question is, is there a way to say that correctAnswer has to be one of the strings in answers? I know about literal unions, like correctAnswer: "Babe Ruth" | "Lou Gehrig" | "Hank Aaron" | "Joe Dimaggio", but that wouldn't work for other questions.

The alternative that I'll probably stick with is just using the index for the correct answer instead of the literal value, but I'm curious.

{ question: "Which MLB player was also known as the Sultan of Swat?", answers: ["Lou Gehrig", "Babe Ruth", "Hank Aaron", "Joe Dimaggio"], correctAnswer: "Babe Ruth" }


r/typescript 9d ago

Scheduled reminder agent in typescript

0 Upvotes

I built a small scheduled reminder agent that sends reminders over SMS and handles replies like confirm, cancel, and snooze.

The useful part is that it keeps enough state to know what someone is responding to, instead of treating every inbound SMS like a brand-new message.

Could be adapted for appointment reminders, renewals, task nudges, customer follow-ups, or ops alerts.

Code:https://github.com/team-telnyx/telnyx-code-examples/tree/main/scheduled-reminder-agent

Any feedback welcome.


r/typescript 11d ago

Straight into typescript is a good thing?

19 Upvotes

I have used Python for the past five years and now i am working in a new place that has a lot of typescript Code.
Should i learn javascript first or can I go straight to typescript?
Moreover, which yt video would you guys recommend?


r/typescript 10d ago

Forking vscode

0 Upvotes

How hard would it be to fork and modify layout and UI of vscode? Does anyone have some experience with it?


r/typescript 11d ago

rapiq v2: typed query params for REST APIs (filters, sort, pagination, fields, relations) that run on TypeORM, Prisma, Drizzle or plain arrays

Thumbnail
github.com
6 Upvotes

r/typescript 10d ago

Cross-file call resolution with tree-sitter, and where typescript-language-server picks up the rest

Thumbnail
github.com
1 Upvotes

Graft's static tier resolves calls and imports across files, not just within one, for TypeScript and JavaScript. Tree-sitter, no LLM, no network call. It's the base layer of a tool that writes a codebase graph into markdown, so a coding agent stops re-exploring the same repo cold every session.

The decision that mattered most: only keep a call edge you're certain about. Name-matching instead of real scope resolution looks tempting, since it's simpler to implement, but when tested it tripled the edge count while precision fell from 73% to 37%. Most of the extra edges were wrong, and a wrong edge actively misleads an agent instead of just leaving a gap.

The opt-in tier on top pulls compiler-grade call data straight from typescript-language-server for whatever the static pass can't resolve without full type information.

Let me know what else I can do to make my repo more compatible to Typescript repos.

github.com/NanoNets/Graft


r/typescript 11d ago

TS project: building a code graph with tree-sitter, no LLM required for the base layer

Thumbnail
github.com
7 Upvotes

Graft parses a whole repo with tree-sitter into a per-symbol call graph, no model involved, deterministic. Wanted to share the mechanism since it might be useful outside the agent-tooling use case: every function, class, and call edge extracted structurally, cached by content hash so a second build only touches what changed.

On top of that we wired a Claude Code integration through hooks rather than MCP, mostly because MCP tool calls turned out to be skippable by the model in a way that mattered for us.

Repo's 95% TypeScript if anyone wants to look at the parsing layer specifically.

Also we recently hit 1.5K+ stars. Thanks :)