Type Systems: Structural Interfaces
Type Systems
Introduction
In this lesson, you'll learn about type systems: structural interfaces in Go. Coming from TypeScript, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.
In TypeScript, you're familiar with type systems.
Go has its own approach to type systems, which we'll explore step by step.
The Go Way
Let's see how Go handles this concept. Here's a typical example:
// Go: structural typing via implicit interface satisfaction
type Writer interface {
Write(data string)
}
// FileWriter implicitly satisfies Writer — no declaration
type FileWriter struct{}
func (f FileWriter) Write(data string) {
fmt.Printf("Writing: %s\n", data)
}
func output(w Writer) {
w.Write("hello")
}
// FileWriter satisfies Writer implicitly — like TypeScript!
output(FileWriter{})Comparing to TypeScript
Here's how you might have written similar code in TypeScript:
// TypeScript: structural typing
interface Writer {
write(data: string): void;
}
// No explicit declaration needed — shape is enough
const fileWriter = {
write(data: string) { console.log(`Writing: ${data}`); }
};
function output(w: Writer) {
w.write("hello");
}
output(fileWriter); // Works — shape matchesYou may be used to different syntax or behavior.
Go interfaces are satisfied implicitly — like TypeScript structural typing
You may be used to different syntax or behavior.
Go has no implements keyword — if a type has the methods, it satisfies the interface
You may be used to different syntax or behavior.
Go types are more primitive: no class hierarchy, just structs + methods
You may be used to different syntax or behavior.
Go is statically compiled but structurally typed — the best of both worlds
Step-by-Step Breakdown
1. Implicit Interface Satisfaction
Go interfaces work like TypeScript interfaces — if a type has all the required methods, it satisfies the interface automatically without any declaration.
interface Greetable { greet(): string; }
const x = { greet() { return "hi"; } };
const g: Greetable = x; // OK — structuraltype Greetable interface {
Greet() string
}
type Person struct{ Name string }
func (p Person) Greet() string { return "hi " + p.Name }
// Person implicitly satisfies Greetable2. No Classes — Structs + Methods
Go has no classes. Data lives in structs. Behavior is added via methods with a receiver. This is like TypeScript interfaces plus separate function implementations.
class Rectangle {
constructor(public width: number, public height: number) {}
area(): number { return this.width * this.height; }
}type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}3. No Inheritance
Go has no inheritance. Composition is achieved with struct embedding — a struct can embed another struct and its methods are promoted.
class ColoredRect extends Rectangle {
constructor(width: number, height: number, public color: string) {
super(width, height);
}
}type ColoredRect struct {
Rectangle // embedded — promotes Width, Height, Area()
Color string
}
cr := ColoredRect{Rectangle{10, 5}, "red"}
fmt.Println(cr.Area()) // promoted method4. any and interface{}
Go's any (alias for interface{}) is the equivalent of TypeScript's unknown/any — a value that can hold anything. Use type assertions to extract the concrete type.
function process(val: unknown): void {
if (typeof val === "string") { console.log(val.length); }
}func process(val any) {
if s, ok := val.(string); ok {
fmt.Println(len(s))
}
}Common Mistakes
When coming from TypeScript, developers often make these mistakes:
- Go interfaces are satisfied implicitly — like TypeScript structural typing
- Go has no implements keyword — if a type has the methods, it satisfies the interface
- Go types are more primitive: no class hierarchy, just structs + methods
Key Takeaways
- Go interfaces are satisfied implicitly — same structural philosophy as TypeScript
- No classes: use structs for data, methods for behavior
- No inheritance: use struct embedding for composition
- any (interface{}) is Go's equivalent of TypeScript's unknown