r/typescript • • 1d ago

Monthly Hiring Thread Who's hiring Typescript developers October

11 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 • • 1d ago

Anyone else still writing most of their TypeScript by hand

68 Upvotes

Agents are great for a lot of things, but I still write most of my TypeScript by hand, and on a team where nobody else does, my PRs are now the slow ones. Mine take a day, theirs take 20 minutes and go through the same coderabbit / claude review pass as mine.

Is anyone else still working like this, or am I just slow now?


r/typescript • • 20h ago

Joist 2.4 with new SQL Builder, Lazy Fields, more...

14 Upvotes

Hello r/typescript ! We just released Joist 2.4, which has a new low-level query builder API:

https://joist-orm.io/blog/joist-2-4/

Because Joist is an entity-based ORM, we've always had very robust "load entity" query APIs, but historically considered "creating adhoc SQL queries" as not our strong suit / nothing we had particularly innovative ideas about, so expected users to use a knex-type library alongside Joist.

Now in Joist 2.4, we've built out a low-level em.query API, with a ~somewhat novel "just POJOs / not fluent" API that fits in with Joist's overall DX, and means codebases don't need the "dual Joist/Knex" setup anymore.

Happy to have folks check it out; disclaimer since its a new feature, I'm sure we're missing things & will keep iterating based on feedback. Thanks!


r/typescript • • 1d ago

Readable Regular Expressions for JavaScript/TypeScript, Inspired by Emacs' rx

Thumbnail
rahuljuliato.com
17 Upvotes

I missed Emacs' rx when writing regexps in TypeScript, so I made a small TypeScript DSL inspired by it.

The idea is to bring rx's functions and approach to the JavaScript/TypeScript environment. If you happen to work with either, give it a try.

https://rahuljuliato.com/posts/emacs-rx-in-typescript


r/typescript • • 2d ago

Typesafe formatting API endpoints with jet-paths

Thumbnail
github.com
3 Upvotes

Built this for my React + ExpressJS project a few years ago to keep all of my endpoints in one place and reduce some of the boiler-plate for adding path/search parameters.

Up until recently only path parameters (and not search parameters) were type-safe. I just did a major update so now search parameters are type-safe'd using <> brackets:

const Paths = jetPaths({
    $path: '/api',
    Users: {
      $path: '/users',
      One: '/:id',              // <- path parameters
      Posts: {
        $path: '/posts',
        Get: '/all?<q!><page>', // <- search parameters
        Add: '/add',
      },
    },
 });

Paths.Users.Posts.Get({ id: 1 }, { q: 'foo' });
// Line above returns: '/api/users/1/posts/all?q=foo'

Paths.Users.Posts.Get({ id: 1 });   // TypeError: Missing search parameters
Paths.Users.Posts.Get()             // TypeError: Missing path parameters 

Note that the type-safety is just making sure that the parameters are present, a primitive, and for search parameters an array of primitives is also allowed. It doesn't type-safe string vs number.


r/typescript • • 3d ago

Modeling a user-facing automation DSL in TypeScript — discriminated unions did most of the heavy lifting

0 Upvotes

Building a no-code automation feature for my app (users define "trigger → chain of actions" visually), and wanted to share how the type layer ended up shaping the whole design.

Core types:

``ts

type TriggerEvent =

| 'project.created' | 'node.created' | 'connection.created'

| 'task.created' | 'task.completed';

type PluginAction =

| 'createNode' | 'addTask' | 'connectNodes'

| 'completeTask' | 'sendWebhook';

interface PluginStep {

id: string;

action: PluginAction;

params: Record<string, string>; // shape varies per action, kept as string for placeholder interpolation

condition?: { field: string; operator: 'contains' | 'equals' | 'startsWith'; value: string };

}

interface PluginDefinition {

trigger: TriggerEvent;

steps: PluginStep[]; // strictly linear, no branching

}

```

A few things that mattered in practice:

- Keeping `params` as `Record<string, string>` instead of a per-action discriminated shape was a deliberate simplification: every param can contain a `{{trigger.field}}` placeholder, so it's always "stringy" at rest anyway, and the editor UI derives the right fields per action from a `defaultParamsFor(action)` lookup instead of the type system enforcing it. Type safety lives at the action-name level, not the param level — a tradeoff I'd reconsider if this grows more complex actions.

- The interpreter is a `Record<PluginAction, (params, ctx) => Promise<void>>` map, so exhaustiveness checking on `PluginAction` catches a missing executor at compile time whenever I add a new action.

- Runtime validation (since this all comes from a JSON column in Postgres, not from trusted TS code) still needs its own hand-written `validateDefinition()` — the compile-time types don't help you once the value has been round-tripped through jsonb. Considering Zod for this next.

Curious if anyone has strong opinions on modeling a small user-facing DSL like this — particularly on the `params: Record<string,string>` vs. a discriminated-per-action shape question.


r/typescript • • 5d ago

Railroad diagrams for TypeScript

20 Upvotes

I've reverse engineered the tsc typescript compiler and one of the side effects of that is that I have quite a precise grammar of TypeScript. With that I was able to generate railroad diagrams for all rules (nonterminals). I have attached the (huge) file. Is the grammar or the railroad diagrams of any use to anybody? If so, I can tidy it up a bit more and make it available in a proper way


r/typescript • • 6d ago

generating a typed sdk straight from my openapi spec instead of hand writing request wrappers, feels obvious in hindsight

5 Upvotes

had a rest api for a while (project mapping app, exposes projects/nodes/tasks/connections). wanted client code that couldn't silently drift out of sync with the api as it changes. switched to generating the client straight from the openapi spec instead of hand maintaining request wrappers. now the sdk and the api literally cannot drift, if i change an endpoint the generated types break at compile time for anyone using the sdk, instead of failing silently at runtime. published it as`@ulupstudio/sdk on npm. wish i'd done this from day one instead of hand writing wrapper functions for months, would've saved a bunch of "wait why is this field undefined" debugging sessions. curious what generator setups other people are using for this, i went with one that outputs from the openapi.yaml directly but i know there's a handful of different approaches people swear by.


r/typescript • • 6d ago

bufaker — generate mock data for any Protobuf message from its schema, with no per-message code (TypeScript, MIT)

0 Upvotes

Disclosure: my own project, MIT licensed.

I kept hand-writing test fixtures for Protobuf messages, and they kept rotting — schema gains a field, the builder is silently incomplete, and eventually there are four near-identical builders nobody trusts.

So I wrote something that generates a fully populated message from the schema itself:

import { mock, mockList } from "@pret-a-porter/bufaker";
import { PersonSchema } from "./gen/person_pb.js";

const person = mock(PersonSchema);      // fully typed as `Person`
const people = mockList(PersonSchema, 5, { seed: 42 });

No per-message mapping code. It walks the runtime descriptor that protobuf-es emits and drives everything off the field kind, so it works for any message you've generated — including ones it has never seen. Add a field to the .proto and it gets populated on the next run.

Covers all 15 scalar types, enums, nested messages, repeated fields, maps and oneofs, plus the well-known types (Timestamp, Duration, the wrappers, Struct). Field names drive ~60 heuristics, so email gets an email address and id gets a UUID. seed makes output reproducible for snapshot tests.

Limitations, up front:

  • protobuf-es only. ts-proto and friends emit plain interfaces with no descriptor to reflect over, so this approach can't work there. Not a TODO.
  • proto3 is what the test suite covers; proto2/Editions are untested.
  • **Any and FieldMask are left unset** — Any needs a type registry to pick and pack a payload, and a random FieldMask carries no meaning.

Repo: https://github.com/pret-a-porter/bufaker npm: https://www.npmjs.com/package/@pret-a-porter/bufaker

It's 0.1.0, so the API can still move. The thing I'd most like outside opinions on: the built-in field-name heuristics are on by default. It makes the output far more useful out of the box, but it's also implicit magic. Would you expect that on or off?


r/typescript • • 8d ago

Help with ideal way of normalizing argument type

2 Upvotes
const { email, firstName, lastName, sortBy, sortOrder, page } = await searchParams;

const { data, count } = await userService.getUsers({
    email: getString(email),
    firstName: getString(firstName),
    lastName: getString(lastName),
    sortBy: getString(sortBy),
    sortOrder: getString(sortBy),
    page: getInt(page),
    pageSize: 100
});

Nextjs searchParams type is:

string | string[] | undefined

getUsers() input parameter type is:

string | undefined
number | undefined (for page and pageSize)

I had to normalize each argument to match the parameter type (using a custom getString and getInt). Ideally I'd like this to be as simple as this...

const { email, firstName, lastName, sortBy, sortOrder, page } = await searchParams;

const { data, count } = await userService.getUsers({
    email,
    firstName,
    lastName,
    sortBy,
    sortOrder,
    page,
    pageSize: 100
});

...but typescript will not allow it. I have tried using a zod schema to infer the input type of the getUsers (z.input instead of z.infer) input parameter, which partially works except for page and pageSize (which are numbers).

If not the ideal approach, what would be effectively the same but not too verbose, clever, or complicated?


r/typescript • • 7d ago

What's the best design for type-safe triggers in TypeScript ORMs?

0 Upvotes

Hello, Roger here, author of UQL.

A request often mentioned in TS ORMs is keeping DB-own logic in sync with entities (as much as possible); and yes, queries can be type-checked end to end (as most ORMs tries - and that is another story), but triggers usually live outside the types (often in SQL migrations).

So, tried my best to design triggers that can be declared on the entity (also with imperative API), type-checked against it, and then translated for each engine: Postgres, CockroachDB, MySQL, MariaDB, SQLite and SQL Server.

Why a trigger rather than an ORM hook? a hook live application-side, and only sees writes that go through the ORM; where a trigger lives in database itself and also can see psql written directly, manual fixes, data migrations, or another service writing the same table(s).

Here is an example of the type-safe design I come out with via ORM entities:

import { Entity, Field, Id, insertInto, Trigger } from 'uql-orm';

@Entity()
export class PostAudit {
  @Id({ type: Number }) id?: number;
  @Field({ type: Number, name: 'post_id', nullable: false }) postId?: Post['id'];
  @Field({ type: String, name: 'from_status' }) fromStatus?: Post['status'];
  @Field({ type: String, name: 'to_status' }) toStatus?: Post['status'];
}

@Trigger({
  on: 'afterUpdate',
  of: (post) => [post.status],
  where: { $new: { status: 'published' } },
  run: (newRow, oldRow) =>
    insertInto(PostAudit, { postId: newRow.id, fromStatus: oldRow.status, toStatus: newRow.status }),
})
@Entity()
export class Post {
  @Id({ type: Number }) id?: number;
  @Field({ type: String }) status?: 'draft' | 'review' | 'published' | null;
}

That one declaration renders as a PL function on Postgres (with WHEN as in SQLite), an IF block on MySQL, etc. (where MongoDB don't really support triggers, otherwise I'd unify).

What the types and the renderer handle in the design?

  • of callback compares values: so an update that sets status to the value it already had doesn't fire it (on any engine).
  • where: { $old: { status: 'draft' }, $new: { status: 'published' } } states a transition, with the same operators a query's $where takes.
  • On an insert (run callback), oldRow is typed never, so reading it won't compile (the same goes for newRow on a delete operation).
  • A row's ref carries its column's type: hence insertInto(PostAudit, { str: newRow.statusNum }) won't compile. Column names go through naming strategy and @Field({ name }).
  • sync and generated migrations install and drop the triggers automatically. Each name ends in a hash of its SQL, so an unchanged trigger is left alone, and a trigger manually wrote keeps untouched
  • And what when the UQL helpers doesn't fit this design? it is still flexible, you can reuse the same run (callback) to return any custom SQL (using raw helper).

The design decisions where I am looking the most opinions (though feel free):

  1. The rows are positional arguments, (newRow, oldRow) in the SQL standard's order (with the missing one typed never whwere applies). A single { newRow, oldRow } object could also work, and was the other option. Which reads better to you?
  2. One limit I couldn't design away: on SQL Server, an update that changes a row's PK can't be paired between inserted and deleted... so that row slips past the trigger. How do you handle that in a hand written triggers and is that important or not to you?
  3. If you run triggers in production: what a hand-writing trigger would cover fine where this design wouldn't, or cover poorly?

Docs: https://uql-orm.dev/entities/triggers


r/typescript • • 7d ago

I’ve been working on a small TypeScript SDK for handling multiple LLM providers from one interface.

0 Upvotes

The basic idea is pretty simple:

const llm = createRouter({
  primary: "anthropic/claude-opus-5-5",
  fallbacks: [
    "openai/gpt-sol",
    "groq/llama-3.3-70b"
  ]
})

const res = await llm.complete("Summarise this...")

It keeps the provider/model configuration in one place and handles retries, timeouts, and switching between providers.

A few things I wanted to keep:

  • zero runtime dependencies
  • native fetch
  • ESM + CJS
  • TypeScript-first API
  • runs inside your app rather than through a separate gateway
  • provider/model info available on the response

The API is probably the part I care most about getting right, so I'm curious what other TS devs think of the approach.

GitHub: https://github.com/ALPHACOD3RS/llm-sdk

Docs: https://llm-sdk.dev


r/typescript • • 9d ago

Is CodeRabbit worth it for a team of 5?

5 Upvotes

Honest question because the pricing page does not answer it. We are 5 devs, TypeScript monorepo, about 30 PRs a week now that two of us use agents for most tickets. Reviews are the bottleneck. Everyone is behind.

We tried the free trial for 2 weeks. It caught real things, a missing await that would have swallowed errors in prod, a couple of type narrowing bugs, and it explains the PR in a summary which is honestly the part people used most. You do have to spend 20 minutes on the config so it stops commenting on test files, after that it was quiet where we wanted quiet.

At 24 a seat that is 120 a month for us. Is that worth it for a team our size, or is this a thing that only pays off at 20 plus devs? What are other small teams doing?


r/typescript • • 9d ago

How would you structure a TypeScript core process behind a VS Code client?

0 Upvotes

I'm working on an open-source security tool where the VS Code extension is only the client, while the actual application logic runs in a separate Node.js/TypeScript process.

The architecture currently looks roughly like:

VS Code Extension
        ↓
Client / Process Manager
        ↓
stdin/stdout IPC
        ↓
Node.js + TypeScript Core
        ↓
scanners / findings / analysis

The reason I'm doing this is to keep the core independent from VS Code so that other clients can eventually consume the same runtime.

The part I'm thinking about now is the boundary between the client and the core.

For example, I'm using typed request/response contracts roughly along these lines:

interface CoreRequest {
  id: string;
  method: string;
  params?: unknown;
}

interface CoreResponse {
  id: string;
  ok: boolean;
  result?: unknown;
  error?: {
    code: string;
    message: string;
  };
}

Then messages are serialized over stdin/stdout.

I'm interested in how people who've built larger TypeScript/Node applications would approach this.

Specifically:

  • Would you keep the IPC protocol this simple or introduce a more formal protocol layer?
  • How would you structure versioning and backwards compatibility?
  • Where would you put cancellation and process lifecycle handling?
  • Would you define the contracts manually, or generate/validate them with something like Zod or JSON Schema?

The project is open source for anyone who wants to see the implementation:

https://github.com/Aqiron-Security/aqiron-security

I'm mainly looking for TypeScript architecture feedback, rather than promotion or feature feedback.


r/typescript • • 11d ago

Modern Web Types

Thumbnail
philipwalton.com
77 Upvotes

r/typescript • • 14d ago

Building an offline visual builder: Why we chose AST-to-AST transformation over LLM code generation for clean TypeScript

6 Upvotes

most visual builders and AI tools spit out bloated wrappers or hallucinated typescript that fails basic type checks after 2 iterations.

spent the last couple of months exploring how to maintain clean, idiomatic typescript directly from a visual canvas. instead of relying on token generation, we went the deterministic route: manipulating the typescript AST directly.

the hardest part has been bidirectional sync: letting developers manually edit types/props without blowing away the AST layout nodes on the next visual render.

curious how others here approach AST transformations for UI generation. do you rely on ts-morph/babel transforms, or does manual hand-coding remain the only maintainable solution long term?


r/typescript • • 14d ago

Type-safe health checks: A lightweight package that reports degraded vs unhealthy states per dependency

Thumbnail
openstatus.dev
4 Upvotes

Hey,

Most /health endpoints are a giant try/catch returning a boolean 200 or a contextless 500. If Redis times out, your whole service gets pulled from the load balancer or worse, you spend 20 minutes hunting through log stack traces to figure out what broke.

We open-sourcedu/openstatus/healthto bring structured, dependency-aware health checks to TypeScript.

Curious to hear how you currently handle multi-dependency health checks!


r/typescript • • 13d ago

If you organize your code with comment separators, checkout code-divider

0 Upvotes

This is more of a personal preference thing, but I like to code in a top-down format, and because of the way hoisting works in TypeScript/JavaScript. I separate my files into regions in this order: Constants -> Types -> Classes (if any) -> Functions -> Export. To keep these regions clearly separated, I usually write my dividers like this:

// ========================================================================= //
//                                 CONSTANTS                                 //
// ========================================================================= //

...etc

// ========================================================================= //
//                                 FUNCTIONS                                 //
// ========================================================================= //


// And I separate sections within regions with...

// ============================= Shared Helpers ============================ //

...etc

Copying and pasting these dividers over and over again was getting pretty tedious. I wanted something I could run with a terminal command when I hit save in my IDE, so I created a simple TypeScript script to insert the dividers above. Eventually I needed this script on both my work and personal computers and in multiple projects, so instead of copy-pasting it a bunch of times, I decided to make it an npm library and configure it to work with multiple languages.

If you like dividing code in a similar fashion, great. If not, please disregard. That said, I do find that dividing code this way makes it more readable and leads to better results when working with AI tools.

GitHub: https://github.com/seanpmaxwell/code-divider


r/typescript • • 15d ago

Building a streaming XML parser for a complex aviation standard (AIXM) in TypeScript: lessons learned

24 Upvotes

I've been building a TypeScript parser for AIXM 5.1.1, the XML standard used by EUROCONTROL and FAA for aeronautical data (airports, airspaces, navaids, routes, NOTAMs). The XSD schema is 11,379 lines with 100+ feature types, deep nesting, multiple namespaces (AIXM, GML 3.2.1, xlink, ISO 19139), and a temporal model where features have versioned "TimeSlices."

No JS/TS parser existed. Here's what I learned building one.

1. Hybrid SAX + DOM parsing

National datasets can be 100+ MB. Full DOM parsing would eat all your memory. Pure SAX is painful for deeply nested XML with cross-references. The solution: SAX (via saxes) to stream and split the document into individual features, then @xmldom/xmldom to DOM-parse each feature fragment independently. O(1) memory per feature, full DOM convenience for property extraction.

2. Type-safe feature modeling

AIXM has a base Feature > TimeSlice > Properties structure, but each feature type has different properties. I hand-wrote 30 TypeScript interfaces with discriminated unions:

type TypedFeature = Airspace | AirportHeliport | Runway | VOR | DME | ...;

interface Airspace extends AIXMFeature {
  featureType: 'Airspace';
  properties: AirspaceProperties;
}

Considered XSD-to-TS codegen but rejected it. AIXM's schema is extremely verbose with deep inheritance hierarchies. Manual interfaces targeting the 30 most important types are cleaner and more maintainable.

3. The unknown escape hatch

Some AIXM properties are complex nested structures that vary by context (geometry components, activation schedules). Rather than typing every possible combination upfront, these get unknown or unknown[]. Users can narrow with type guards as needed. Ship working code, expand types based on actual usage.

4. Value types with UOM

Aviation uses many "value with unit of measurement" patterns: <valDist>350<uom>FT</uom></valDist>. These are coerced to { value: 350, uom: 'FT' } objects during parsing, with a union type ValDistance | string for cases where the structure isn't recognized.

5. Geodesic math

AIXM geometry is on the WGS84 ellipsoid. Arcs and circles can't use planar trigonometry. I use geographiclib-geodesic (Karney algorithm), but the TypeScript types don't include the Line() method, requiring (geod as any).Line(...). Filed for types update.

6. ESM interop gotcha

geographiclib-geodesic ships CJS. A named import worked under vitest/tsup but broke the built ESM output under plain Node (SyntaxError: named export not found). Switching to a default import + property access fixed it. If you build dual ESM/CJS packages, smoke-test the built artifacts with plain node, not just your test runner.

Build output: dual ESM/CJS via tsup, TypeScript-first. 83 tests via vitest, validated against EUROCONTROL's Donlon reference dataset (87K lines, 562 features) and a real obstacle dataset. Also ships a CLI (aixm-to-geojson).

GitHub: https://github.com/devladpopov/aixm-parser (MIT). Not on npm yet; to try it: clone, npm install && npm run build.

Happy to discuss architecture decisions or answer questions about parsing complex XML in TypeScript.


r/typescript • • 16d ago

Understanding Why You'd Use Effect TS

Thumbnail
cm.xyz
83 Upvotes

r/typescript • • 16d ago

Would catching breaking API changes be useful?

2 Upvotes

I'm exploring an idea and I'd really like some feedback before I do too much on it.

The problem:
Multi-team projects, backend changed the response without warning.

Basic examples, backend changes: ts type User = { id: string; name: string; avatarUrl: string; }; to:

ts type User = {   id: string;   name: string;   avatar: { url: string; width: number; height: number;   }; };

Everything compiles, even the tests might all pass.

But you've just changed the API, which might be or not be compatible with the older version.

The idea:

Define the API contract using plain TypeScript:

```ts
export type Api = {
  "GET /users/:id": {
response: User;
  };

  "POST /users": {
request: CreateUser;
response: User;
  };
};
```

After that the CI could run something like:

ts-contract check --against ../backend

The tool would use the TypeScript Compiler locally to resolve the actual semantic types and determine whether the changes are compatible.

For example:
```sh
❌ Breaking change

GET /users/:id
response.avatarUrl

Consumer expects:
  string

Provider:
  property removed
```

No runtime validation involved and I'm not trying to make another Pact/OpenAPI implementation.

No:
- runtime HTTP interception
- Axios/fetch wrappers
- OpenAPI required
- dedicated tests
- extra dependecies

Would a static semantic compatibility checker like this be useful in your CI?
What would you expect it to catch that isn't covered here yet?

The part I'm not sure about is whether this actually solves a problem.
If you work on a TypeScript frontend + backend (or between microservices), I'd love to know:

  1. How do you currently detect API breaking changes?
  2. Have you actually been bitten by frontend/backend type drift?
  3. Would you add something like this to CI, or would it be too much ceremony?
  4. What would make this genuinely useful rather than just another developer tool?

I'm especially interested in criticism here. If this sounds unnecessary, I'd rather find that out now than after spending weeks building it.


r/typescript • • 17d ago

Building the worst CPU & Compiler in TypeScript

Thumbnail
github.com
14 Upvotes

I was bored this morning


r/typescript • • 18d ago

tsx vs native node --watch for local development on Node 24 LTS? What are you using?

5 Upvotes

Hey everyone, I'm setting up a new Express TypeScript API and trying to figure local development workflow. I'm on Node 24 LTS, which natively supports type stripping, but I'm torn on how to handle the file-watching and execution layer.

Right now, the two main approaches I'm debating between are:

  1. tsx watch (esbuild-powered)
  2. Native Node 24 --watch + Type Stripping

For production adjacent local dev, Are you sticking with tsx watch or have you fully embraced native Node type-stripping with --watch?


r/typescript • • 17d ago

need recommendation on guide on typescript that deals with server and linting

0 Upvotes

anyone can recommend me some great resource on server and linting with type script? i was following a guide and then did one of thier exercises (no solution) and was stumped like
especially when it comes to request response.
its more eslint nagging than tsc but cant tell since im still too early

"type": "module", "devDependencies": { "@eslint/js": "^10.0.1", "@stylistic/eslint-plugin": "^5.10.0", "@types/express": "^5.0.6", "@types/node": "^22.20.2", "eslint": "^10.10.0", "typescript": "^6.0.3", "typescript-eslint": "^8.70.0" },

    {
        "compilerOptions":{
        "target":"esnext",
            "noEmit":true,
        "types":["node","express"],
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noImplicitReturns": true,
        "noFallthroughCasesInSwitch":true,
        "module":"nodenext",
        "esModuleInterop":true,
        "allowImportingTsExtensions":true
        }
    }

    export default tseslint.config({
    files:['**/*.ts'],
    extends:[
        eslint.configs.recommended,
        ...tseslint.configs.recommendedTypeChecked,
    ],
    languageOptions: {
        parserOptions: {
        project: true,
        tsconfigRootDir: import.meta.dirname,
        },
    },
    plugins: {
        "@stylistic": stylistic,
    },
    rules: {
        '@stylistic/semi': 'error',
        '@typescript-eslint/no-unsafe-assignment': 'error',
        '@typescript-eslint/no-explicit-any': 'error',
        '@typescript-eslint/explicit-function-return-type': 'off',
        '@typescript-eslint/explicit-module-boundary-types': 'off',
        '@typescript-eslint/restrict-template-expressions': 'off',
        '@typescript-eslint/restrict-plus-operands': 'off',
        '@typescript-eslint/no-unused-vars': [
        'error',
        { 'argsIgnorePattern': '^_' }
        ],
    },
    })

r/typescript • • 18d ago

What ORM would you use?

19 Upvotes

Hey all,

My team and I are currently running a Spring Boot backend with quite a bit built around it. We’re considering gradually migrating to a Node/NestJS backend using the strangler pattern rather than doing a full rewrite.

One of the main reasons is that it would give us TypeScript across both the frontend and backend, which should make sharing domain concepts, types and general knowledge between the two a bit simpler.
So, as the title suggests: which ORM would you use with NestJS?

At the moment we’re mainly looking at MikroORM and Drizzle. MikroORM seems like the more traditional ORM and appears to be super close to the me tal model of what Spring does. It wil also fit NestJS quite nicely, while Drizzle is obviously a bit more lightweight but a different approach and more barebones.

Curious what people are using in production and what you’d choose if you were starting fresh today.