Belajar Scala - Tipe Data & Type System
Episode 5 of 23

Belajar Scala - Tipe Data & Type System

Membedah type system Scala yang ekspresif: tipe primitif dan Unit, container yang menghilangkan null (Option, Either, Tuple), lalu mekanisme pendefinisian tipe sendiri lewat case class, enum, given dan using untuk typeclass, serta opaque type untuk abstraksi yang aman.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 4 kalian menguasai val, var, dan def, sekarang kita membedah hal yang membuat Scala begitu dihargai: type system-nya. Di bahasa lain, tipe sering dianggap "pembatas"; di Scala, tipe adalah alat desain yang dipakai untuk mencegah bug sebelum kode dijalankan.

Mengapa episode ini penting? Karena sebagian besar keunggulan Scala di produksi — refactoring yang aman, API yang ekspresif, dan kode yang "compiles = works" — berasal dari type system. Kalian tidak perlu hafal semua detail; yang perlu dipahami adalah cara berpikir dengan tipe sebagai kontrak.

Tipe Dasar dan Unit

Scala mewarisi tipe primitif JVM, tetapi memperlakukan semuanya sebagai objek:

TipeDeskripsiContoh
IntBilangan bulat 32-bit42
LongBilangan bulat 64-bit42L
DoublePecahan presisi ganda3.14
Booleantrue / falsetrue
StringTeks"halo"
CharSatu karakter'a'
Unit"Tidak ada nilai" (analog void)()

Unit perlu perhatian khusus: ia adalah tipe yang hanya punya satu nilai, ditulis (). Fungsi yang "tidak mengembalikan apa-apa" sebenarnya mengembalikan Unit:

Unit sebagai hasil efek
def log(msg: String): Unit = println(s"[log] $msg")

Unit menandai fungsi yang punya efek samping. Ini kode yang jujur: tipe bilang "jangan harapkan nilai berguna dari ini".

String Interpolation

Manipulasi string di Scala idiomatis memakai interpolator s"...":

String interpolation
val user = "Sari"
val balance = 99.5
println(s"User $user punya saldo $balance")
Ekspresi di dalam interpolasi
println(s"1 + 1 = ${1 + 1}")

Di dalam prose, ingat: { dan } literal harus dibungkus backtick — interpolation s"${...}" adalah satu-satunya tempat umum keduanya muncul.

Option, Either, dan Tuple

Tipe-tipe ini adalah jawaban Scala atas null dan multi-nilai.

Option: Ada atau Tidak Ada

Option[A] punya dua kemungkinan: Some(a) atau None. Tidak pernah null:

Option menghilangkan null
def findUser(id: Int): Option[String] =
  if id == 1 then Some("Sari") else None
 
findUser(1)   // Some(Sari)
findUser(99)  // None

findUser secara tipe memaksa pemanggil menangani kemungkinan "tidak ada". NPE (NullPointerException) yang jadi mimpi buruk Java dihilangkan dengan desain, bukan disiplin. Pattern matching untuk menanganinya ada di episode 7.

Either: Dua Kemungkinan Berlabel

Either[L, R] merepresentasikan hasil yang bisa Left(l) (biasanya error) atau Right(r) (biasanya sukses):

Either untuk hasil yang bisa gagal
def divide(a: Int, b: Int): Either[String, Int] =
  if b == 0 then Left("tidak bisa dibagi nol")
  else Right(a / b)
 
divide(10, 2)  // Right(5)
divide(10, 0)  // Left(tidak bisa dibagi nol)

Konvensi: Right adalah sukses. Episode 16 akan membahas penanganan error secara menyeluruh.

Tuple: Kelompok Nilai Heterogen

Tuple mengelompokkan beberapa nilai dengan tipe berbeda:

Tuple
val person = ("Sari", 25, true)   // (String, Int, Boolean)
println(person._1)                // Sari

Sejak Scala 3, tuple bisa di-destructure dengan pola yang lebih jelas:

Destructuring tuple
val (name, age, active) = ("Sari", 25, true)
println(s"$name berusia $age")

Mendefinisikan Tipe Sendiri

case class

case class adalah cara standar membuat tipe data immutable dengan banyak perilaku gratis (equality berbasis nilai, copy, pattern matching):

case class
case class User(id: Int, name: String)
 
val u1 = User(1, "Sari")
val u2 = User(1, "Sari")
u1 == u2  // true - equality struktural, bukan referensi
 
val u3 = u1.copy(name = "Sari Dewi")  // salinan dengan perubahan

enum: ADT ala Scala 3

enum mendefinisikan Algebraic Data Type (ADT) — sekumpulan kemungkinan yang jelas:

enum
enum PaymentStatus:
  case Pending
  case Paid(amount: Double)
  case Failed(reason: String)

Nanti di episode 7 kita akan memakai ini untuk modeling domain. Yang perlu diingat sekarang: enum di Scala 3 menggantikan pola sealed trait Scala 2, dengan sintaks lebih ringkas dan ekshaustif yang diperiksa compiler.

given dan using: Typeclass Scala 3

Mekanisme given/using menyelesaikan masalah "perilaku untuk tipe" tanpa inheritance. Bayangkan fungsi yang butuh "cara mengurutkan" — ia bisa meminta instance tersebut secara implisit:

given dan using
trait Ordering[A]:
  def compare(a: A, b: A): Int
 
given IntOrdering: Ordering[Int] with
  def compare(a: Int, b: Int): Int = a - b
 
def maxOf[A](a: A, b: A)(using ord: Ordering[A]): A =
  if ord.compare(a, b) >= 0 then a else b
 
maxOf(3, 7)  // 7 - IntOrdering dipakai otomatis

Fungsi maxOf tidak perlu tahu bagaimana membandingkan; ia meminta penyedia. Inilah pola typeclass yang jadi tulang punggung library seperti cats dan circe.

opaque type: Abstraksi Tanpa Overhead

opaque type membungkus tipe lain sehingga kalian bisa memberi semantik tanpa overhead runtime:

opaque type
opaque type UserId = Int
 
object UserId:
  def apply(value: Int): UserId = value
  extension (id: UserId) def value: Int = id
 
val id: UserId = UserId(42)

Di luar scope definisi, UserId tidak bisa disamakan dengan Int — compiler mencegah UserId(42) + 1 atau mencampurnya dengan Int biasa. Ini menghilangkan kelas bug "salah ketik argumen bertipe angka".

Note

Urutan belajar yang baik: kuasai Option/Either/case class dulu (dipakai setiap hari), lalu enum (episode 7), lalu given/using dan opaque type secara bertahap. Empat hal terakhir ini yang membuat type system Scala "ekspresif" — tetapi tidak perlu semuanya dalam satu hari.

Common Pitfalls

  • == null di kode Scala — jika kalian menulis ini, berhenti: Option ada justru untuk menghindarinya.
  • Menggunakan _1, _2 tuple berlebihan — destructuring lebih terbaca.
  • case class dengan field mutable (var) — ini melanggar semangat immutability; hampir selalu salah.
  • given yang tidak terpakai — compiler Scala 3 memberikan peringatan; hapus instance yang menganggur.

Penutup

Inti yang harus dibawa pulang:

  • Tipe dasar Scala mencakup Int, Long, Double, Boolean, String, Char, dan Unit.
  • Option menghilangkan null, Either merepresentasikan hasil gagal/sukses, Tuple mengelompokkan nilai.
  • case class memberi equality struktural dan copy; enum mendefinisikan ADT; given/using membangun typeclass; opaque type memberi abstraksi tanpa overhead.
  • Type system Scala adalah alat desain, bukan sekadar pemeriksa kesalahan.

Di episode 6 selanjutnya, kita masuk dunia data: collections dan immutable dataList, Vector, Map, Set yang immutable secara default, transformasi map/filter/flatMap/fold, dan pola-pola yang akan kalian pakai setiap hari. Sampai jumpa di episode 6!