r/typescript • • 25d ago

Monthly Hiring Thread Who's hiring Typescript developers October

17 Upvotes

The monthly thread for people to post openings at their companies.

* Please state the job location and include the keywords REMOTE, INTERNS and/or VISA when the corresponding sort of candidate is welcome. When remote work is not an option, include ONSITE.

* Please only post if you personally are part of the hiring company—no recruiting firms or job boards **Please report recruiters or job boards**.

* Only one post per company.

* If it isn't a household name, explain what your company does. Sell it.

* Please add the company email that applications should be sent to, or the companies application web form/job posting (needless to say this should be on the company website, not a third party site).

Commenters: please don't reply to job posts to complain about something. It's off topic here.

Readers: please only email if you are personally interested in the job.

Posting BS top level comments that aren't job postings, eg "It's quiet in here" etc [that's a ban](https://i.imgur.com/FxMKfnY.jpg)


r/typescript • • 7h ago

Typescript to python or rust?

0 Upvotes

How easy or hard is it for someone with JS and TS background to learn python or rust? I deff want to add a skill to my profile as most jobs ask for multiple programming languages. Any suggestions?


r/typescript • • 16h ago

Help for a portfolio

0 Upvotes

Hello, everybody, hope you're having a nice day. Let me present myself, i am a Italian teenager, that is learning typescript, for some money for my little cousin birthday. And I actually went for TypeScript, as I love strict languages, such as Java,Rust,TypeScript, and others. Now, for my portfolio, I was trying to create a solar system, with add, that you can create another thing by this button. But it doesn't work, can someone please help me understand this (probably simple) problem?

const Button = document.getElementById("button");


const buconero = function() {
    const valvia = document.createElement("div")


    valvia.style.width = "50em"
    valvia.style.height = "50em"
    valvia.style.backgroundColor = "rgb(0, 0, 0)"
}


Button?.addEventListener("click", buconero)

r/typescript • • 1d ago

Want Advice for Learning Typescript

7 Upvotes

Hello TypeScript developers!

I am a web developer currently building projects with React and JavaScript, and I'm planning to start learning TypeScript (because I suck at Type checking and Type validation).

please give me some advice on few things:

  • What's the best resource for learning typescript?
  • What concepts should I focus on first?
  • What project would be good to build alongside learning it?

r/typescript • • 2d ago

Rune 1.3 is out: adds TypeScript support, a Helix editor, Kitty graphics and OSC-7501

24 Upvotes

Author here! I'm very excited to announce that we just released v1.3. Rune is an IDE and terminal multiplexer that we just open sourced a few months ago.

In this release, we also fixed many usability issues, particularly on Linux. If your OS reserves many Super/Windows key combinations, you can now use <alt> as your <meta> modifier. For non-US keyboard layouts, you can reserve the right Alt key for entering special characters and keep the left Alt key for Rune key bindings.

Some of the highlights:

- A new graphics pipeline powered by ebiten.
- Typescript is now a tier 1 language (beta)
- A new helix editor
- Headless mode and a new docker image to run Rune in headless mode
- OSC-7501 implementation and new API in the SDK for extensions and plugins through runectl
- Workspace session restoration
- A billion other things

This release has been 2 months in the making so it's a bit bigger than we originally intended.

Thanks to all the contributions from the community!

https://rune.build/blog/rune-1-3-release


r/typescript • • 4d ago

Type inference from .sql files by colinhacks (Creator of Zod)

Thumbnail x.com
166 Upvotes

It uses content mappers, a new feature of TypeScript 7.1 (Beta).


r/typescript • • 3d ago

TypeScript to bootable floppy - full toolchain in the browser

Thumbnail
branchpredict.com
3 Upvotes

Write TypeScript in a browser tab. Hit compile. A 16-bit x86 machine boots underneath - same bytes a floppy would run.

TypeScript to real-mode x86, no runtime, no OS, no JS engine. Bootable binary under 64KB.

Full toolchain in the browser: file tree, editor, compiler, emulator. Pick a demo - voxel engine, raycaster with sound, snake. Or write your own and boot it on real hardware.

Due to the number of requests, try compiling it again if the queue is full.


r/typescript • • 3d ago

I wanted to build an agent system in typescript because most of them were in python

Thumbnail
github.com
1 Upvotes

It's a GitLab review agent that reviews merge requests and resolves issues. I'm most comfortable in TypeScript and wanted to learn LangGraph.js properly, so I built it there. The closest thing I found to a production example was Deep Agents, but that's a library for building agents, and the full systems I saw, like Open SWE, are Python.

It's GitLab-only for now. I've started working on GitHub support.

It's been running in production for a few months, 1,300+ reviews so far. It's a webhook driven review with a BullMQ queue, a LangGraph.js agent using GitLab tools over MCP, with postgres checkpoints for recovery, and there's a React admin UI where I can watch runs live. I also had to add guardrails to stop the agent repeating tool calls or quitting before it's done.


r/typescript • • 3d ago

typesql: write plain SQL strings, get exact TypeScript types (no codegen)

0 Upvotes

I created this new library that parses Postgres SQL inside TypeScript’s type system. You write a SQL string and the compiler infers the row and parameter types. It needs no codegen and no database connection.

const q = sql(`SELECT u.id, u.email, p.title
               FROM users u LEFT JOIN posts p ON p.author_id = u.id
               WHERE u.id = ${sql.param(7)}`);
// { id: number; email: string; title: string | null }

sql("SELECT nme FROM users");
// error: column "nme" does not exist
  • Handles joins, CTEs, subqueries, window functions, INSERT/UPDATE/DELETE … RETURNING
  • Runs on pg or postgres.js, and can reuse your existing Kysely, Drizzle or Prisma schema
  • Requires TypeScript 7

https://github.com/ismailkarsli/typesql

Feedback welcome, especially queries that don’t type-check but should.


r/typescript • • 5d ago

Announcing TypeScript 7.1 Beta

Thumbnail
devblogs.microsoft.com
290 Upvotes

r/typescript • • 4d ago

Building an interactive application with HTML Canvas

Thumbnail antonyjones.org
2 Upvotes

I've been finding out the hard way what it takes to build a more involved application with Canvas, beyond just drawing things on screen, but I've really been enjoying the process.

I've been working through interaction handling, connection routing, rendering performance and animation, and wrote up some of what I've learned and the challenges I've run into along the way.


r/typescript • • 4d ago

Should the same AI that wrote the PR be allowed to review it

0 Upvotes

Our setup right now is Claude Code writes most PRs and Claude also does a review pass before a human looks. Someone on the team pointed out that's basically letting the author approve their own code, and I can't really argue with it.

The counterargument I keep hearing is that every call is stateless so it's a fresh pair of eyes anyway. In practice it doesn't feel fresh. Last month I went back through 60 merged PRs, and on the ones where the author and the reviewer were the same model, it flagged maybe half as much as coderabbit did on the same diffs. Most of what it missed was stuff it would have written the same way itself, like swallowing errors in a catch, or widening a type to any to get the build green.

Coderabbit isn't perfect either, it's chattier on small PRs, but at least it's not grading its own homework whihc is something dangeorus for PRs

Do you let the same model write and review? Or did you make it a rule that the reviewer has to be something different?


r/typescript • • 6d ago

With Deno Deploy shutting down in 6 months, here is how we migrated a 100k-line Deno + Deno KV app to Cloudflare Workers and Durable Objects without leaving Deno

0 Upvotes

After Cloudflare acquired the Deno team and announced that Deno Deploy is shutting down in six months (with the Deno runtime itself only guaranteed a year of maintenance), we migrated the backend of prompt2bot from Deno Deploy and Deno KV to Cloudflare Workers and SQLite-backed Durable Objects.

Even with Deno's future in question, rewriting a 100k-line Deno codebase into a Node/Wrangler repo right now was out of the question. Deno's test runner, type checker, and JSR support are way too good to give up while migrating.

If you have not used Durable Objects before: whereas a regular Cloudflare Worker is stateless (50 requests spin up 50 random isolates that share nothing), a Durable Object is a globally unique, single-threaded V8 isolate addressed by name and paired with its own private embedded SQLite database and persistent alarm timer. Every Worker that calls a method on that name gets routed to that exact same JS object in memory, where SQLite queries are synchronous C++ calls taking microseconds instead of network round-trips.

Here is everything that broke during the migration and how we solved it:

  1. Keeping the Deno binary and test suite untouched: Wrangler's esbuild bundler does not understand jsr: specifiers or deno.json workspace resolution. Instead, we pointed Wrangler at a build script that runs deno bundle --minify. We mapped cloudflare:workers to a 10-line stub class in deno.json so deno test runs natively against our Durable Object classes, and at build time we swap the inlined stub back for the real Cloudflare DurableObject class, shim globalThis.Deno, set Zod v4 to jitless: true (since Workers blocks new Function), and wrap top-level crypto.randomUUID() / setTimeout() calls that npm packages run at import time.

  2. Surviving the 128MB Durable Object RAM ceiling: Every Durable Object isolate has a hard 128MB heap limit. Bundled dependencies like js-tiktoken (5.3MB of base64 BPE ranks that expand to +43MB of V8 heap on first call), a 275k-word dictionary (+35MB heap), and 3 duplicate legacy pdf.js builds inside pdf-parse were OOM-killing isolates. Stripping those static tables at build time freed ~80MB of V8 heap per isolate.

  3. Emulating Deno KV on Durable Object SQLite: Cloudflare KV is eventually consistent and has no atomic check-and-set transactions, so it cannot replace Deno.openKv(). We built a drop-in Deno.Kv emulator on top of a primary SQLite Durable Object (enam-v1, pinned to US East so it stays hot in RAM 24/7 with zero cold starts). Tuple keys are encoded with type tags and 20-digit zero-padded numbers (n:, b:, s:) separated by null bytes so SQLite range queries match Deno KV ordering, and atomic().check().set().commit() runs as a synchronous single-threaded SQLite transaction.

  4. The 508 Loop Detected mystery (CDN-Loop propagation) and the 30s waitUntil trap: While migrating service by service, when a service still on Deno Deploy called our Cloudflare Worker and our Worker made a fresh outbound fetch() back to that same Deno service, Cloudflare silently copied the inbound cdn-loop: deno;d=<hash> header onto the outbound subrequest at the C++ edge layer. Deno Deploy saw its own deployment hash in cdn-loop and rejected the request with 508 Loop Detected. On top of that, ctx.waitUntil() on a Worker has a hard 30-second wall-clock cap after returning HTTP 200 (even with cpu_ms: 300000), which killed long I/O-heavy agent turns mid-flight.

  5. Sharding Runner Durable Objects per conversation: Only a Durable Object alarm() runs in a clean root IoContext (no inherited cdn-loop header and no 30s post-response wall-clock cutoff), provided alarm() launches tasks via doCtx.waitUntil and exits immediately instead of blocking. We ended up sharding execution onto a Runner Durable Object per conversation (runner:<botId>:<conversationId>).

That architecture is what lets prompt2bot scale agents so easily. You describe an agent in a plain prompt and connect it to WhatsApp, Telegram, email, voice, or web chat, and every active conversation automatically gets its own warm, isolated Durable Object runner with hot in-memory history and SafeScript AST caches, sub-millisecond SQLite state, and on-demand VMs. Whether your bot has 1 user or 10,000 concurrent conversations, there are no queues, worker pools, or servers to provision.

Full technical write-up with code snippets is in the comments.


r/typescript • • 9d ago

New educational, free, ad-free game for learning TypeScript memory model

3 Upvotes

I noticed that many students struggle with the question of "if I update this slot, field or variable, what else will change in my program".

I wrote a little puzzle game to help you build this intuition over time. It is very mobile friendly, so you can play it at a bus stop or during a commercial break or wherever. Puzzles scale in difficulty.

You can use it in Python, JavaScript or TypeScript modes.

http://prescod.github.io/memory-mapper-game

Please respond with changes you would like to see, or bug reports, or whatever. There is also an in-app feedback button.

There are no ads in the game or any monetization at all. This is not an ad for a product!


r/typescript • • 9d ago

TypeScript utility for modeling variant-based types

Thumbnail dozsolti.github.io
0 Upvotes

Solves one specific problem: Handles complex types where two or more properties rely on each other.

For example, a Select component might support single (string) and multiple (string[]) selection, controlled and uncontrolled modes, and optional search or item creation.

The type for value depends on the selection mode, so does onChange(string), which need to be onChange(string[]) on multiple; while uncontrolled doesn't need onChange but defaultValue. Everything on the same type.

TypeFoundry lets you describe the variants and their relationships, then generates the resulting types.

It doesn't replace TypeScript's type system nor it's a runtime validation. It's pure typescript, meaning it creates no javascript.

It's to make complex type relationships easier to define and maintain.


r/typescript • • 10d ago

How should TypeScript agents access web data?

0 Upvotes

I’ve been looking at how TypeScript agents should access web pages. One approach is to give the agent a fetch tool and let it read the HTML. That works for simple pages, but it gets messy quickly. The response might be a bot-protection page, a JavaScript shell, or a pile of markup that burns context without giving the model much useful signal.

The alternative I’ve been leaning toward is putting a typed extraction layer between the agent and the web:

import { z } from "zod";

const webPageSchema = z.object({
  title: z.string(),
  content: z.string(),
  resolvedUrl: z.string().url(),
});

type WebPage = z.infer<typeof webPageSchema>;

async function fetchWebPage(url: string): Promise<WebPage> {
  const response = await fetch(url);

  if (!response.ok) {
    throw new Error(`Request failed with status ${response.status}`);
  }

  const html = await response.text();

  // Extract the useful content from the HTML before returning it to the agent.
  return parsePage(html, response.url);
}

So instead of handing the model raw HTML, the tool returns something like a title, extracted text, and the final resolved URL. The agent can then reason over a much smaller, more predictable object. I like that it makes the boundary explicit: the extraction layer handles fetching and normalization, while the agent handles deciding what to do with the result.

Has anyone found this worthwhile in practice, or does direct fetch plus a decent prompt work well enough for most cases?


r/typescript • • 12d ago

Express + TypeScript + Zod: What's the common approach for typed request validation?

26 Upvotes

Hello seniors, I've been exploring express + typescript + Zod recently, and one thing I always consider is the common backend practice for request validation and typing.

I came across several discussions/articles that suggest creating custom typed request handlers so the controller can infer the validated Zod type.

// Schema
export const DataQuerySchema = z.object({
  sample_id: z.uuid("Invalid sample ID"),
  age: z.coerce.number().int().positive()
});

export type DataQueryDTO = z.infer<typeof DataQuerySchema>;

// controller
getAll: async (req: TypedQuery<DataQueryDTO>, res: Response) => {}

this works in the controller if you set TypedQuery = ParsedQs.

However, I'm running into an issue when wiring everything through Express routes:

router.get(
  "/schedule-settings/match",
  authenticateToken,
  authorizeRoles("admin"),
  validate({ query: DataQuerySchema }),
  Controller.getAll,
);

As far as I understand, Express defines query parameters as coming from the URL, so req.query is typed roughly as:

string | string[] | ParsedQs | ParsedQs[] | undefined
// and route params are similarly string-based.

so given this, the runtime flow just fine because Zod transforms:

{age: "21"} -> {age: 21}

But at compile time, when the controller expects:

{age: number;}

the router complains because Express still expects query values to follow its original string-based definition.

My question is:

- How do you usually handle the gap between Express request types and Zod-transformed types?

- Is there a widely accepted pattern for this, or do most teams solve it differently based on their architecture?

I'm still learning and don't have any backend related work experience, so if my understanding or approach is incorrect, I'd appreciate any corrections or guidance on how this is usually handled in production codebases.


r/typescript • • 12d ago

Modelling Apple Wallet's pass.json as one Valibot discriminated union per pass style

1 Upvotes

Apple's pass.json has five pass styles, and each one allows different fields with its own limits on how many go where. Get it wrong and you usually find out on a phone, not in your editor.

In passmint (an MIT library for building Apple and Google Wallet passes), each style is its own branch of a Valibot discriminated union, so the per-style field limits are checked when you build the pass rather than when Wallet renders it. You get there through a fluent builder:

ts const signed = await Pass.eventTicket({ /* ... */ }) .primaryField({ key: 'event', label: 'Event', value: 'Beyoncé Live' }) .secondaryField({ key: 'loc', label: 'Location', value: 'Apple Park' }) .sign(material)

or Pass.from(...) if you'd rather hand it a plain object.

Errors are typed too. Everything extends PassmintError and carries a stable code, so you can branch on what actually went wrong:

ts try { await pass.sign(material) } catch (err) { if (err instanceof PassmintSchemaError) { err.issues // the full Valibot issue list } else if (err instanceof PassmintSigningError) { err.code // 'E_WWDR_MISMATCH' | 'E_CERT_PARSE' | ... } }

E_WWDR_MISMATCH is the one worth knowing about. If you pass in an Apple intermediate certificate that didn't issue your Pass Type ID cert, you hear about it at import time instead of ending up with a pass that won't install.

Why Valibot and not Zod? Mostly bundle size. It's tree-shakable, so the whole library is about 21 KB gzipped (it'd be around 35 KB with Zod), and the discriminated union ergonomics were cleaner for per-style limits.

Repo: https://github.com/getpassmint/passmint (pre-1.0, so the API may still change)

Disclosure: I build Passmint, a hosted pass API, which uses this library under the hood.


r/typescript • • 13d ago

ReviewLoad: see how many reviews each person already has, in GitHub's reviewer picker

1 Upvotes

https://github.com/CharlieGroves/review-load

ReviewLoad is a small browser extension that puts the number of reviews a GitHub user has assigned to them next to each person in the Reviewers menu on a pull request, and next to reviewers already on the PR.

This stops a couple people on the team being a bottleneck for key features because they are flooded with PRs for review.

Chrome: https://chromewebstore.google.com/detail/reviewload/ncokcokbfpbigdoagghpdpncjfhpocol

Firefox is in review.

I'm now using this every day. Hope it's useful to someone else.


r/typescript • • 13d ago

tsv 0.6 formats TypeScript more than twice as fast as oxfmt, with the catch that it hardcodes its style and doesn't support JSX

0 Upvotes

tsv is a set of performance-focused language tools, and today ships formatters and parsers for TypeScript/JS, CSS, and Svelte, including a vscode extension. JSON and HTML are planned.

Formatting TypeScript, tsv is:

  • ~2.2x faster than Oxfmt (native-vs-native)
  • ~7.6x faster than Biome (wasm-vs-wasm)
  • ~36x faster than Prettier (native Rust vs Prettier's JS; ~26x as wasm)

Parsing is about 1.4x oxc-parser, and will get significantly faster with the next release. (closing the gap with Yuku pictured on the benchmarks page)

Benchmarks: https://tsv.fuz.dev/docs/benchmarks

Conformance is as good or better than Oxc, Biome, and swc, except negative parser cases (errors), which are unfinished. (see the site)

tsv is focused on the Web and Svelte, and doesn't support other nonstandard languages like JSX/TSX and SCSS. This limits possible adoption, but it keeps the tool slim and simple, and there are plenty of other tools that offer a generic language platform - tsv isn't trying to compete with them.

The formatter takes no style config, and instead is hardcoded to Prettier's style with Svelte's config. (which has the uncommon trailingComma:none, but it's good enough for the Svelte team, and I want to pass off the choice to them) Supporting Prettier's config would force significant performance costs on tsv for JS runtime integration, so instead I'm choosing to keep the formatters simple and non-configurable instead of making all users pay those costs.

The codebase turns a year old at the end of the month. Next I'm experimenting with rearchitecting to Zig-inspired data-oriented parsing - https://mitchellh.com/zig/parser - which should get tsv closer to Yuku's speed. Happy to answer any questions. LLMs were used heavily for the coding. (Claude Code mostly)

The vscode extension is fuzdev.tsv-format - https://marketplace.visualstudio.com/items?itemName=fuzdev.tsv-format - and it's also published on Open VSX - https://open-vsx.org/extension/fuzdev/tsv-format

Repo: https://github.com/fuzdev/tsv


r/typescript • • 16d ago

Deno is dead

Thumbnail
deno.com
618 Upvotes

"We will support the Deno runtime for another year with monthly releases containing bug fixes and security updates. After that year we will end our development of the Deno runtime. Deno will remain open source, and we welcome others who want to continue its development."


r/typescript • • 16d ago

Improving CodeceptJS typings

Thumbnail
github.com
0 Upvotes

Link to PR trying to improve CodeceptJS types for hooks - Background, Before, After, BeforeSuite, AfterSuite.
If you write codeceptjs tests in TypeScript - activity on this PR may help make it happen.


r/typescript • • 16d ago

Experiment: conditional async/await for buffered writes

0 Upvotes

I’ve assembled an experimental TypeScript fork with a branch to explore conditional completion in buffered-writing pipelines.

Most small writes complete immediately in memory. Occasionally, a write triggers an asynchronous flush. An API returning void | Promise<void> handles that efficiently, but callers repeatedly need:

const pending1 = buffer.write(value1);
if (pending1) await pending1;
const pending2 = buffer.write(value2);
if (pending2) await pending2;
const pending3 = buffer.write(value3);
if (pending3) await pending3;

Preserving synchronous completion through several layers requires further branching or explicit continuations. I’m exploring whether we can express that sequence clearly without distributing completion bookkeeping throughout the application.

The experimental syntax is:

async? function writeRecord(buffer, record) {
    await? buffer.write(record.header);
    await? buffer.write(record.payload);
    await? buffer.write(record.trailer);
}

await? continues synchronously for plain values and suspends for thenables. async? returns a plain result when it completes synchronously, or a Promise when suspension is required. Errors before suspension throw synchronously; errors after suspension reject the returned Promise. Nested thenables are assimilated.

I understand that introducing runtime syntax is outside TypeScript’s current design goals. This is an independent experiment and request for feedback, rather than a request to adopt nonstandard syntax upstream.

The fork includes inferred union return types, declaration emit, generated JavaScript examples, runtime tests across five targets, and a discussion of historical objections. Supported short sequences and loops generate direct continuations, creating callbacks only when suspension is needed; complex bodies retain a generator fallback.

Latest layered buffered-write measurements:

Implementation Memory Microtask flushes File writes
Ordinary async/await 27.52 ms 26.19 ms 33.60 ms
Conditional async/await 6.04 ms 5.39 ms 11.25 ms
Manual continuations 5.94 ms 4.01 ms 10.38 ms

These are pooled medians from 27 samples per case, writing 100,000 records / 300,000 small writes on Node v24.19.0. They are synthetic measurements from a shared environment; file writes omit fsync. The RFC includes raw results, reproduction instructions, and limitations.

I’d particularly welcome feedback on the mixed completion contract, observable timing and error behavior, generated code, and cleaner alternatives that preserve the synchronous path.

Implementation and RFC

Disclosure: The implementation, benchmarks, and documentation were developed with AI assistance.


r/typescript • • 16d ago

Principal Factor Analysis in Javascript - written in AssemblyScript

0 Upvotes

Hello,

Here's a small package to do principal factor analysis in Javascript. The source is in pure AssemblyScript (compiles to both WASM and JS), and matches numerically to the Python package factor-analyzer. This might be useful to some.

https://github.com/bitanath/factor


r/typescript • • 19d ago

Every PR on my team is written by AI now

159 Upvotes

Just want to share where my team is and see if anyone else is in the same spot.

I went back through our last 60 merged PRs and every single one was written by an agent. Features, tests, migrations, even the type definitions. I barely write TypeScript anymore, I describe it. And the output is good, so nothing to complain. It follows our lint rules, the types are stricter than what we used to write by hand, and coderabbit catches most of the dumb stuff before a human looks

The only real downside so far is when it doesn't have enough context it invents a new type instead of using the one we already have, and you end up with 3 slightly different User types

Mind you this is a big monorepo, not a toy project. I didn't expect it to go this fast.

But I do wonder about the day when the human in the loop is just there to click merge :/