By using this site, you agree to the Privacy Policy and Terms of Use.
Accept
World of SoftwareWorld of SoftwareWorld of Software
  • News
  • Software
  • Mobile
  • Computing
  • Gaming
  • Videos
  • More
    • Gadget
    • Web Stories
    • Trending
    • Press Release
Search
  • Privacy
  • Terms
  • Advertise
  • Contact
Copyright © All Rights Reserved. World of Software.
Reading: Building Modular Code with Composition: Go vs TypeScript | HackerNoon
Share
Sign In
Notification Show More
Font ResizerAa
World of SoftwareWorld of Software
Font ResizerAa
  • Software
  • Mobile
  • Computing
  • Gadget
  • Gaming
  • Videos
Search
  • News
  • Software
  • Mobile
  • Computing
  • Gaming
  • Videos
  • More
    • Gadget
    • Web Stories
    • Trending
    • Press Release
Have an existing account? Sign In
Follow US
  • Privacy
  • Terms
  • Advertise
  • Contact
Copyright © All Rights Reserved. World of Software.
World of Software > Computing > Building Modular Code with Composition: Go vs TypeScript | HackerNoon
Computing

Building Modular Code with Composition: Go vs TypeScript | HackerNoon

News Room
Last updated: 2025/04/03 at 4:55 AM
News Room Published 3 April 2025
Share
SHARE

If you’ve worked with class inheritance long enough, you’ve probably reached a point where it starts feeling frustrating and restrictive. Then we all know and can appreciate how Object Composition patterns can simplify code and make express behavior of code better. This is not a write up on Composition vs Inheritance, for more on that take a look at Composition over Inheritance

Instead of thinking in terms of “A is a B,” composition lets us think in terms of “A has behavior X”. This approach makes our code more modular, flexible, and reusable.

Go is not an object-oriented language. Staying true to its “Keep it Simple” philosophy, Go does not support classes, objects, or inheritance.

Interface Composition in TypeScript

In Typescript we can leverage type intersections (&) to compose types, building types with all the features we need.

Let’s say we’re working with animals. Some animals live on land, some in water, and some (like amphibians) can do both. Instead of using inheritance to model this, we can compose behaviors:

type Animal = {
    sound: () => string
}

type AquaticAnimal = Animal & {
    swim: () => void
}

type LandAnimal = Animal & {
    walk: () => void
}

type Amphibian = AquaticAnimal & LandAnimal

const dolphin: AquaticAnimal = {
    sound() {
        return 'ee ee ee'
    },
    swim() {
        console.log('🐬 🐬 🐬')
    },
}

const alligator: Amphibian = {
    sound() {
        return 'sssss'
    },
    swim() {
        console.log('💦 💦 💦')
    },
    walk() {
        console.log('🐊 🐊 🐊')
    },
}

console.log((alligator as Animal).sound()) // Works fine
console.log((dolphin as LandAnimal).walk()) // TypeScript will warn you!

Why This Works Well

  • No rigid hierarchies – Instead of a deep class tree, we mix and match behaviors.
  • Flexibility – We can create new types by combining existing ones, without modifying the originals.
  • Compile-time safety – TypeScript prevents us from calling walk() on an AquaticAnimal.

But what about Go? Since Go doesn’t have classes or inheritance, how does it handle composition?

Interface Composition in Go

How would we go about achieving this in Go you ask?

In Go, you can embed interfaces inside each other, kind of like snapping Lego blocks together to build something bigger. This makes it easy to break down complex ideas into smaller, more manageable pieces.

Since we’re composing functionality instead of stacking up rigid inheritance chains, we get way more flexibility and avoid those fragile, complicated class hierarchies. Plus, embedding means less copy-pasting, so we keep our code DRY ☂️ without extra hassle.

package main

import "fmt"

// Define Animal behavior
type Animal interface {
	Sound() string
}

// Define Aquatic behavior
type AquaticAnimal interface {
	Animal
	Swim() string
}

// Define Land behavior
type LandAnimal interface {
	Animal
	Walk() string
}

// Amphibian embeds both AquaticAnimal and LandAnimal
type Amphibian interface {
	AquaticAnimal
	LandAnimal
}

// Dolphin implements AquaticAnimal
type Dolphin struct{}

func (d Dolphin) Swim() string {
	return "🐬 🐬 🐬"
}

func (d Dolphin) Sound() string {
	return "ee ee ee"
}

// Crocodile implements Amphibian (both swimming and walking)
type Crocodile struct{}

func (c Crocodile) Swim() string {
	return "💦 💦 💦"
}

func (c Crocodile) Walk() string {
	return "🐊 🐊 🐊"
}

func (c Crocodile) Sound() string {
	return "argh"
}

func main() {
	// Create instances
	willy := Dolphin{}
	ticktock := Crocodile{}

	// Call behaviors
	fmt.Println(willy.Sound()) // ee ee ee
	fmt.Println(willy.Swim())  // 🐬 🐬 🐬

	fmt.Println(ticktock.Sound()) // argh
	fmt.Println(ticktock.Swim())  // 💦 💦 💦
	fmt.Println(ticktock.Walk())  // 🐊 🐊 🐊

	// Using interface values
	var animal Animal = willy
	fmt.Println(animal.Sound()) // ee ee ee

	animal = ticktock
	fmt.Println(animal.Sound()) // argh
}

Real world examples

Go’s standard library provides several fundamental interface types that form the backbone of its I/O and string-handling capabilities. Some key examples include:

  • fmt.Stringer defines a String() method, allowing a type to represent itself as a string.
  • io.Reader reads data into a byte slice, commonly used for streaming input.
  • io.Writer writes a byte slice to an output destination, such as a file or network connection.

These interfaces are widely implemented across the standard library and third-party libraries, enabling seamless integration with files, network I/O, custom serializers, and more.

A great example is net.Conn from the net package, which implements both io.Reader and io.Writer:

  • As an io.Reader, net.Conn allows you to call Read() to receive incoming data.
  • As an io.Writer, it supports Write(), enabling data transmission over the connection.

This dual implementation makes net.Conn a powerful tool for handling network communication efficiently.

Conclusion

Composition helps us avoid deep, rigid hierarchies and instead focus on what objects can do.

  • In TypeScript, we achieve composition using type intersections (&), allowing us to mix and match behaviors.
  • In Go, we use interface embedding, making it easy to compose functionality without inheritance.
  • Go’s standard library is built on interface composition, making it highly modular and reusable.

By thinking in terms of “has-a” instead of “is-a”, we can write cleaner, more maintainable code across different programming languages.

Next Steps: Try refactoring some of your own code using composition instead of inheritance. You’ll be surprised at how much cleaner and more flexible it becomes!

Bonus question

Will it compile? If not, why? Drop your answers in the comments! 🤔

package main

type A interface {
	sayHi() string
}

type B interface {
	sayBye() string
}

type C interface {
	A
	B
}

func main() {
}

Further Reading


Hope you enjoyed reading this as much as I enjoyed writing it.

If this helped you think differently about composition, share it with a fellow developer. Also, if you’ve got thoughts or questions, drop them in the comments—I’d love to discuss more!

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Twitter Email Print
Share
What do you think?
Love0
Sad0
Happy0
Sleepy0
Angry0
Dead0
Wink0
Previous Article I paid $110 for the PNY 1.5TB PRO Elite Prime microSD card and it still feels like a bargain
Next Article Counterfeit Android Phones Preloaded With a Special Surprise: Malware
Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Stay Connected

248.1k Like
69.1k Follow
134k Pin
54.3k Follow

Latest News

UK Uber drivers’ earnings cut after secretive algorithm changes
News
Advertising growth fuels Bilibili’s Q2 earnings, loss narrows to $83.7 million · TechNode
Computing
Today's NYT Strands Hints, Answer and Help for June 19 #473- CNET
News
7 watches I’d actually buy in the Goldsmiths sale | Stuff
Gadget

You Might also Like

Computing

Advertising growth fuels Bilibili’s Q2 earnings, loss narrows to $83.7 million · TechNode

1 Min Read
Computing

10 Best Miro Alternatives & Competitors in 2025

27 Min Read
Computing

Intel Begins Sending In Kernel Graphics Driver Changes For Linux 6.17

2 Min Read
Computing

Geely to bring Black Myth: Wukong gaming experience to its cars · TechNode

5 Min Read
//

World of Software is your one-stop website for the latest tech news and updates, follow us now to get the news that matters to you.

Quick Link

  • Privacy Policy
  • Terms of use
  • Advertise
  • Contact

Topics

  • Computing
  • Software
  • Press Release
  • Trending

Sign Up for Our Newsletter

Subscribe to our newsletter to get our newest articles instantly!

World of SoftwareWorld of Software
Follow US
Copyright © All Rights Reserved. World of Software.
Welcome Back!

Sign in to your account

Lost your password?