A data type is a classification that tells a programming language which values a piece of data may hold, how those values are represented in memory and which operations are valid on them. Data types are one of the programming fundamentals: every variable, parameter, return value and expression has a type, whether the programmer writes it explicitly or the language infers it.
Types let the compiler or interpreter reject meaningless operations, such as dividing a date by a word, and let it choose efficient machine instructions. They also act as documentation, telling other developers what a function expects and what it returns.
How a data type shapes values and operations
At the hardware level, memory holds only bits. A data type is the interpretation rule that turns those bits into meaning: the same 32 bits can represent a signed integer, a floating-point number or four text characters, depending on the type assigned to them.
A type therefore defines three things. It sets the value domain, such as whole numbers from -2,147,483,648 to 2,147,483,647 for a 32-bit signed integer. It fixes the representation, such as two’s complement or IEEE 754 floating point. It also determines the permitted operations, such as arithmetic for numbers or concatenation for strings.
The same operator can behave differently for different types. In many languages, + adds two integers but joins two strings, and / may perform integer division that discards the remainder or floating-point division that keeps it, depending on the operand types.
Primitive data types and their ranges
Primitive types are the basic building blocks a language provides directly, usually mapping closely to what the processor handles natively. Their sizes vary between languages, but the values below are common in mainstream languages such as C, Java, C# and Rust.
| Type | Typical size | Value range or precision | Typical use |
|---|---|---|---|
| Boolean | 1 byte in most implementations | true or false | Conditions and flags |
| 8-bit integer (byte) | 1 byte | -128 to 127 or 0 to 255 | Raw binary data |
| 32-bit integer | 4 bytes | About plus or minus 2.1 billion | Counters, indexes |
| 64-bit integer | 8 bytes | About plus or minus 9.2 quintillion | Timestamps, large IDs |
| Single-precision float | 4 bytes | About 7 significant decimal digits | Graphics, sensor data |
| Double-precision float | 8 bytes | About 15 to 17 significant digits | Scientific and general math |
| Character | 1 to 4 bytes | One text character or code unit | Text processing |
Two properties cause many bugs. Integer overflow happens when a result exceeds the type’s range, and depending on the language it wraps around, raises an error or is undefined behavior. Floating-point rounding means that values such as 0.1 cannot be stored exactly in binary, so 0.1 + 0.2 is not exactly 0.3.
Composite and abstract data types
Beyond primitives, languages let programmers combine types into larger structures and define their own. These composite types model real-world entities and collections.
| Category | What it holds | Examples |
|---|---|---|
| String | Sequence of characters | Names, messages, file paths |
| Array or list | Ordered collection of elements | Measurements, search results |
| Record or struct | Named fields of different types | A customer with name and age |
| Class or object | Fields plus methods that act on them | An account with deposit logic |
| Enumeration | Fixed set of named values | Order status: new, paid, shipped |
| Map or dictionary | Key-value pairs | Settings, lookup tables |
| Optional or nullable type | A value or the absence of one | A middle name that may be missing |
An abstract data type describes behavior rather than layout: a stack is defined by push and pop operations, regardless of whether it is implemented with an array or a linked list. This separation between interface and implementation is a core idea of good program design.
Static, dynamic, strong and weak typing
Languages differ in when types are checked and how strictly they are enforced. These are two independent dimensions, which is why a language can be dynamically typed yet strongly typed, as Python is.
| Discipline | Meaning | Example languages | Main trade-off |
|---|---|---|---|
| Static typing | Types checked before the program runs | Java, C#, Rust, TypeScript | Early error detection, more declarations |
| Dynamic typing | Types checked while the program runs | Python, JavaScript, Ruby | Flexibility, errors found later |
| Strong typing | Few implicit conversions between types | Python, Rust, Haskell | Fewer surprises, more explicit casts |
| Weak typing | Many implicit conversions | JavaScript, C in places | Convenience, unexpected results |
Type inference narrows the gap between static and dynamic styles. In languages such as Kotlin, Rust and TypeScript, the compiler deduces a variable’s type from its initial value, so code stays concise while still being checked at compile time.
Type conversion and choosing the right type
Converting a value from one type to another is called casting or type conversion. Implicit conversion happens automatically, for example promoting an integer to a float in mixed arithmetic, while explicit conversion is written by the programmer and can lose information, such as truncating 3.9 to 3.
| Value to store | Recommended type | Reason |
|---|---|---|
| Money amounts | Decimal type or integer cents | Avoids binary rounding errors |
| Counts and indexes | Integer of sufficient width | Exact and fast |
| Physical measurements | Double-precision float | Wide range, adequate precision |
| Yes or no state | Boolean | Clear intent, minimal ambiguity |
| Fixed set of options | Enumeration | Prevents invalid values |
| Identifiers like phone numbers | String | Leading zeros and symbols matter |
A classic mistake is storing money in floating-point types, which produces cent-level rounding errors in totals. Another is storing phone numbers or postal codes as integers, which removes leading zeros and invites arithmetic that makes no sense for identifiers.
The simple explanation
A data type is like the label on a storage container in a kitchen. A jar marked sugar holds sugar, a bottle marked oil holds oil, and you know what you can do with each one.
In a program, the type tells the computer what kind of information a value is, such as a number, a piece of text or a yes-or-no answer. That way the computer knows how to store it and stops you from doing something meaningless, like multiplying a name by a date.
How it is used in practice
A developer builds an invoicing feature and initially stores prices as double-precision floats. After summing 1,000 line items of 0.10 each, the report shows 99.9999999999986 instead of 100.00, and accounting flags the mismatch.
The developer changes the price field to a decimal type in the code and in the database, and stores quantities as integers. Totals now match to the cent, and a static type check in the build also catches a place where a quantity string from a web form was being added to a number. The change removes a whole class of rounding and conversion errors before the feature reaches customers.