Skip to content

Go You Won't Find in TypeScript

Why some Go concepts have no TypeScript counterpart

Section titled “Why some Go concepts have no TypeScript counterpart”

TypeScript is a layer on top of JavaScript — it runs in a garbage-collected runtime (V8 or Deno), ships as source or transpiled bundles, and every object is implicitly a reference. Go was designed from scratch as a compiled, statically typed, systems-capable language. That different foundation means Go has an entire category of features that TypeScript simply does not have, not because TS forgot them, but because the underlying model is different.

This module covers those features. Work through each lesson to build intuition for the parts of Go that will feel the most foreign at first — and the most powerful once they click.

LessonThe Go-only concept
Pointers& / * — explicit memory addresses
Value vs ReferenceStructs and arrays copy; slices and maps share
Defer / Panic / RecoverDeterministic cleanup and structured panic handling
Struct EmbeddingComposition without class inheritance
Goroutines PreviewLightweight threads — not async/await
Static Binaries & ToolchainOne binary, zero runtime, instant cross-compile
Generics DifferencesType parameters with interface constraints — not structural

Each of these features shares one underlying motivation: explicitness and predictability at low cost. Go prefers making side-effects visible (who owns this memory? does this function take a copy or share the original?) over the implicit convenience that JavaScript/TypeScript provide. That trade-off leads to fewer surprise bugs in production — at the cost of slightly more upfront thought.

TypeScript
// TypeScript has no pointers, no explicit value-copy semantics,
// no defer keyword, no struct embedding, no goroutines,
// and no notion of "compile to a static binary".
// These are all Go-specific.
Go
// Go — a taste of each concept in this module
package main
import "fmt"
type Logger struct{ prefix string }
func (l Logger) Log(msg string) { fmt.Println(l.prefix+":", msg) }
type Service struct {
Logger // embedded — no inheritance needed
name string
}
func riskyOp() (err error) {
defer func() { // defer: always runs on exit
if r := recover(); r != nil {
err = fmt.Errorf("recovered: %v", r)
}
}()
panic("something went wrong")
}
func double[T int | float64](v T) T { return v * 2 } // generics
func main() {
svc := Service{Logger: Logger{prefix: "SVC"}, name: "demo"}
svc.Log("starting") // promoted method from Logger
x := 10
p := &x // pointer to x
*p = 99 // mutate through pointer
fmt.Println("x via pointer:", x)
err := riskyOp()
fmt.Println("riskyOp err:", err)
fmt.Println("double 7:", double(7))
}
Which of the following is a Go concept with NO direct TypeScript equivalent?
Why does Go use pointers instead of always passing references?
Which Go feature replaces verbose try/finally cleanup blocks?