Type system features
- Definition
- Language features regarding the types of data

Features
Static Typing (C
, C++
, Java
, C#
, Rust
, Go
, Haskell
, Scala
, TypeScript
, Swift
) Variables have types known at compile time, enabling type checking and optimizations before execution.
Dynamic Typing (Python
, JavaScript
, Ruby
, PHP
, Lisp
, Perl
) Variables can hold values of any type and type checking is done at runtime.
Type Inference (Haskell
, Scala
, Rust
, Kotlin
, Swift
, F#
, OCaml
) The compiler automatically deduces the type of a variable or expression.
Duck Typing (Python
, Ruby
, JavaScript
, PHP
) Type compatibility is determined by behavior (methods/properties) rather than inheritance.
Nominal Typing (Java
, C++
, C#
) Types are considered compatible based on explicit declarations and names.
Structural Typing (TypeScript
, Go
, Scala
, OCaml
) Type compatibility is determined by the structure (fields/methods) of types rather than names.
Union Types (TypeScript
, Flow
, Haskell
, Elm
, F#
) A value may be one of several explicitly declared types.
Nullable Types (Kotlin
, TypeScript
, Swift
, C#
) Types that explicitly allow null or undefined values to improve safety.
Optional Types (Swift
, Rust
, Haskell
, Scala
, F#
) Variables can either contain a value or be empty (None
, Nil
, null
).
Generics / Parametric Polymorphism (Java
, C#
, C++
, Rust
, TypeScript
, Scala
, Haskell
) Allows code to be written generically for any data type while preserving type safety.
Type Constraints (Scala
, Haskell
, Rust
, C#
) Restrict generic types to certain conditions or interfaces.
Dependent Types (Idris
, Agda
, Coq
, F*
) Types that depend on values, enabling very precise type constraints at compile time.
Refinement Types (LiquidHaskell
, F*
, Idris
) Types that are enriched with logical predicates to enforce invariants.
Phantom Types (Haskell
, Scala
, Rust
) Compile-time-only types used to enforce constraints without affecting runtime behavior.