| title | Why Forst? |
|---|---|
| description | Design priorities, what you get from Forst, and what the language omits. |
While backend engineering covers a wide surface, some central issues affect everyone:
- Developer experience: everyday work needs fast feedback and low boilerplate.
- Performance: prod needs to keep up when traffic spikes and complexity grows.
- Contracts: boundaries need to validate bad data before it reaches domain logic.
Forst is for teams who want all three: one .ft source that ships as native Go while allowing incremental migration within your existing TS or Go codebase.
Similar to TypeScript, Forst allows working within your existing codebase and replacing more and more code over time:
flowchart TB
subgraph jsStack [JavaScript ecosystem]
JS[JavaScript]
TS[TypeScript]
JS --> TS
end
subgraph goStack [Go ecosystem]
Go[Go]
Forst[Forst]
Go --> Forst
end
TS -.->|"types + ergonomics"| JS
Forst -.->|"types + ergonomics"| Go
TypeScript added types on top of JavaScript while keeping the same runtime. Forst does the same on both sides of your stack:
- Go: Ship native binaries with
go buildand typed boundaries layered on top. See Go interop. - Node: Stay type-aligned with the frontend and migrate route by route without a big bang rewrite. See JavaScript interop.
Compare Forst to TypeScript and Go.
How each stack talks to other languages and adopts code incrementally.
| Capability | TypeScript | Go | Forst |
|---|---|---|---|
| Incremental migration | Adopt TS file by file | Mix packages over time | Mix .ft, .go, and legacy JS/TS |
| Go module ecosystem | No (WASM only) | Native | Import Go packages |
| JS / npm ecosystem | Native | No | Call legacy JS/TS via import "./path" js |
| Call backend from Node | Same runtime | No | Generated client + HTTP invoke |
| Shared types (server ↔ client) | Straightforward | Manual / separate | forst generate |
| OpenAPI, RPC, and route files | Separate codegen from schemas | go generate |
Plugins emit them from your .ft backend |
How each language models data, errors, and concurrency.
| Capability | TypeScript | Go | Forst |
|---|---|---|---|
| Static typing | Yes | Yes | Yes |
| Structural typing | Built-in | Structs (nominal) | Built-in (flexible) |
| Mocking & DI | DI libraries | Manual / Fx / Wire | use / with |
| Validation on types | Schema library (Zod, etc.) | Manual checks | Built-in constraints |
| Error handling | Exceptions (try/catch) |
(T, error) values |
ensure, Result, nominal errors` |
| Type narrowing | Discriminated unions, type guards, asserts |
Type assertions | is / ensure, type guards |
| Exceptions | Yes (try/catch) |
Yes (panic/recover) |
No (Go panics possible) |
| User-defined generics | Yes | Yes | No (built-ins, planned) |
| Class inheritance | Yes | No (composition) | No (shapes) |
| Goroutines | Via async/await | Native (go / defer) |
Native (go / defer) |
switch / case |
Yes | Native | Yes (Go-faithful; type switches omitted) |
select / channels |
No | Native | No (planned) |
| Runtime reflection | Limited | Native (reflect) |
No (compile-time focus) |
How you ship, debug, and adopt each stack day to day.
| Capability | TypeScript | Go | Forst |
|---|---|---|---|
| Production runtime | V8, JavaScriptCore | Native | Native Go (compiled from .ft) |
| Execution model | JIT | Native | Native (via Go) |
| Static binary deployment | No | Yes | Yes (via Go output) |
| Language server (LSP) | Yes | Yes (gopls) | Yes (forst lsp) |
| Open source | Yes | Yes | Yes |