Introduction to Data Types: Static, Dynamic, Strong & Weak

    Tim Hurd
    Share

    This article explains what data types are, what is meant by the terms “static”, “dynamic”, “strong” and “weak” when we talk about data types, and why should we even care.

    What Are Data Types?

    In programming, a data type is what we tell the computer the type of data it’s dealing with, e.g. a string, number, or object. When defining a variable, a computer needs both the name and the type of data before it can store and process it. This way it knows much much memory to set aside, how to access it and how to change it.

    You might find it easier to flip around the term and think of it as “the type of data” we’re dealing with. For example, in JavaScript, let name = "sitepoint"; creates a variable called ‘name’ with a type of ‘string’.

    let name = "sitepoint";
    console.log(typeof name);
    // "string"
    

    Each programming language has a different way of handling how it assigns data types (static vs. dynamic) and how flexible (strong vs. weak) they are when trying to change them. You might have read conflicting information about “static” vs “dynamic” data types, as well as “strong” vs “weak” data types. They’re not the same thing, and a language can include a combination of static/dynamic and strong/weak data types:

    • Static vs. Dynamic defines how a language expects you to declare data types. Static typed languages require explicit definition of a data type when they create a piece of data (e.g. variable, parameter, return value). Dynamic languages are the opposite and can infer, or at least try to guess, the type that we’re using.
    • Strong vs. Weak defines how flexibly a language allows operations between data types. For example, strongly typed languages will not allow you to add a float to an integer, without you converting it first, even though they are both numbers. On the other hand, a weak language will try its best to accomodate what the programmer is asking and perform these operations.

    There is no best option with choosing static vs. dynamic or strong vs. weak. A strict language will ensure consistency and reduce the amount of errors you make in your code. As a trade-off you might find yourself writing more verbose code and defining and converting types that may seem obvious to the human eye.

    Why Should We Care About Data Types?

    Every programming language has a data type system. Without a type system, computers wouldn’t know how to represent the data in our programs. They wouldn’t know how to take this type of data and add it to this other type of data or even how to store the data. By specifying a variable as an integer, the computer knows how many bytes it needs to represent the value and, more importantly, how it can perform operations with it. Adding two integers together is a different operation from adding together two strings. The only way the computer knows how to handle the data is by knowing the types of data it’s dealing with.

    You can begin programming without knowing much about the underlying type systems at play. That’s part of the beauty of these higher-level languages. But understanding the types of data you’re dealing with, and how best to represent the data you’re working with, brings huge advantages, such as those listed below.

    • You’ll have more efficient programs that make better use of memory and storage. By knowing that an array of integers occupies less space than an array of doubles can lead to kilobytes or even megabytes of savings when dealing with very large arrays in memory or on the hard disk.
    • It will help you decipher debugging messages and gain a better understanding of problems related to data types. When the program complains it can’t add two numbers because one of the numbers is a string, you understand why. Learning this fact will help you avoid making the mistake of trying to add a number to a string to begin with.
    • Once you know how types work, you can be like Neo from the movie The Matrix and know how to bend the rules. You’ll know when adding an integer to a character how you can get another character and why that works.

    Static vs Dynamic Data Typing Systems

    Static data typed languages are those languages that require the programmer to explicitly define a data type when they create a piece of data (be it a variable, parameter, return value, and so on). Typically, these types are also fixed as being that type for the lifetime of the program, and they don’t change their type. Let’s take a look at an example:

    int myNumber = 42;              // integer data type
    string name = "Rocky Balboa";   // string data type
    final double PI = 3.141592;     // double data type
    
    // Function takes two integer data types, returns an integer data type
    public int add(int a, int b) {
        return a + b;
    }
    

    This example above shows a few variables being defined, and an example of a function that adds two numbers together. As you can see, we are explicitly telling the language (in this case, Java) that we’re dealing with integers, strings and doubles. Without these hints to the compiler, the compiler would not know how to treat myNumber. This is just a name that makes sense to us, not the computer.

    Some languages that are statically typed include Java, C#, C++ and Go. But these are just a few of many.

    Let’s contrast this with a dynamic data typed language. Below is an example:

    $myNumber = 42;           // integer data type
    $name = "Rocky Balboa";   // string data type
    $PI = 3.141592;           // float data type
    
    // Function takes two integer data types, returns an integer data type
    function add($a, $b) {
        return $a + $b;
    }
    

    So, where did all the types go? In this example above, we see that our variables in PHP, a dynamically typed language, don’t explicitly say what types of data they are. If we’re not telling PHP the data types, how does it know? Well, it guesses based on the value being assigned to it. It can correctly guess that $myNumber is an integer because the value 42 is an integer.

    What about the function? It too makes a guess based on the values passed to it. This means that add() could take two integers and return an integer, or it also could take two floats and return a float. The types are inferred and can even change during runtime. We could later, in the same program, say that $myNumber is equal to Tom and it will let us switch the variable to a string.

    A few of the many languages that are dynamic include JavaScript, PHP, Python and Ruby.

    Why Would You Prefer Static Over Dynamic or Vice Versa?

    In the case of static data typed languages, by explicitly telling the compiler up front the types of data you’re dealing with, it can catch common mistakes and errors in code long before deployment. If you define one value to be an integer and another to be string, the compiler can catch an addition error during compile time and won’t let you finish building the program. This is good in that the earlier you catch an error, the stronger your code will be, and the less it will cost you and your clients to fix it. It’s much easier to fix things early than later after deployment.

    So static is the way to go right? Well, the tradeoff is that you have to explicitly define everything before you use it. You have to type more code, you have to know the type of data you’re dealing with beforehand (not always something you know) and you have to know what’s going to happen in your operations. You have to know that 1 / 3 is going to give you 0 and not .33333 and things like that.

    Dynamic languages give you added flexibility in this area. They’re often described by programmers as being “more expressive”. In PHP, for instance, you’ll get .3333... as you might expect. However, the problem is that if the interpreter makes a wrong guess in the data types, you have to know about it. Otherwise it can sneak by. Since we can’t catch everything, code in dynamic languages tends to be a bit more error prone and brittle. Data types in these dynamic languages are typically determined at runtime. This makes it hard to catch many errors until they reach a production environment. It may work fine on your local development machine, but the production runtime environment could be slightly different, yielding some different guesswork by the interpreter.

    JavaScript is one language that is considered dynamic. With the introduction of TypeScript, a superset of JavaScript, programmers introduced the idea of explicitly declaring data types for variables in order to make the language more static. As JavaScript’s popularity has grown — even beyond the browser with tools like Node.js — programmers wanted to add the benefits of static data typing to take out some of the wrong guesswork JavaScript does when dealing with data types. JavaScript is notorious for some of its bad guesswork when dealing with data and its types. This is an example of making JavaScript, a dynamic language, into something more like a statically typed language to catch errors early and lead to healthier code. This is all the more important given that JavaScript is making its way into server-side applications with the help of Node.js.

    In short, static data types give you a strict environment and typically yield stronger code. Dynamic languages give you flexibility and the ability to write code faster, but can lead to more error prone code if you’re not careful in checking your types.

    Strong vs Weak Data Typing Systems

    Strong/weak data types are how a language handles the values it operates on. Will the language quietly make some assumptions when working with the data types and help you out, or will it just stop and complain that it doesn’t know what to do? Let’s take a look at an example of how this works:

    int main() {
        int a = 5;
        std::string b = "5";
    
        // Houston, we have a problem!
        std::cout << (a + b);
        return 0;
    }
    

    In this C++ example, we’re trying to add an integer and a string together. Yes, the language is statically typed, but it’s not trying to cover for the programmer by making b an integer so that it can add two numbers together. It just flags the issue right away and gives up. This check is done when we attempt to compile the program (or sometimes by an IDE as you write it). Here, we’re trying to use the type in a way that is counter to its definition of being a string. Strongly typed languages include C#, Java, Go, Python and C++ to some extent, and they all would flag something like this.

    Now C++ has ways to weaken its strongly typed system, but that’s beyond the scope of this article. We’ll cover weak data types and then talk about strong/weak together and how things aren’t as clear cut as static/dynamic typing.

    A weak data typed languages attempts to help out the programmer as it carries out its operations. Let’s take a look at JavaScript and see how it might do a similar operation to what we did in our C++ example above:

    const a = 5;
    const b = "5";
    
    console.log((a + b));
    

    If you know anything about JavaScript and its quirks, you know that the code above will work without fuss. It won’t point out anything to the programmer. But it won’t log 10 to the console as you might expect. You’d think it would see an integer and a string and go “Whoa, wait a minute here, I don’t know what to do with this!” Instead, JavaScript attempts to coerce, or convert, one of the values to be like the other, do the calculation, give a result and move on. Here the result would be "55" since it converts the value of variable a into a string and then concatenates them. The result would then be a string data type.

    As you can see, the strength of a language is how strongly it attempts to use its types to make sense of the programmer’s intention and moves on.

    Using these terms, we can say a language like Python, which is dynamic, is also strongly typed. You don’t need to explicitly define a type when you create the value (dynamic part), but if you try to and then use that type in a way that it doesn’t expect, it will immediately flag the issue and quit (strong typing).

    Why Would You Prefer Strong Over Weak or Vice Versa?

    Strong languages are rigorous languages. Again, they make sure they know exactly what the programmer intends to do. If an error occurs, it’s more often than not an error by the programmer not understanding the operations. These errors also potentially point the way to a lack of understanding about the problem. If you’re trying to add 5 the number to "5" the string, then perhaps you don’t realize how that’s not going to make sense to a computer. It forces you to come to the truth of the operation and makes you explicitly tell the computer what you want to do (usually with some form of conversion/casting mechanism). This tends to lead to stronger and less error-prone code in production, but adds time and hoops to jump through during development.

    Weak languages, again, lean more on the side of flexibility and expressiveness, by taking away the strict rigor of a strong language and allowing the programmer to get their code up and running. But the down side is that the computer makes assumptions that the programmer may not have intended.

    JavaScript, a weak typed language (that also happens to be dynamic), again was beefed up with TypeScript to make it stronger. TypeScript’s handling of data types allows a programmer to write JavaScript using explicit types and to gain the benefit of a strongly typed language. It catches many errors during compile time and helps keep vague JavaScript assumptions from reaching production systems. But again, this is at the cost of being more formal and rigorous with coding format during development. Even code editors that know TypeScript can flag the errors as you write them. VS Code is one great example that does this.

    Degrees of Strength

    We’ve now looked at strong and weak typing. It’s important to note that, unlike a clear-cut line that exists with static/dynamic typing, languages can show varying degrees of strength or weakness. This puts languages on a spectrum. This is why you find some articles saying that C++ is weak while others say that it’s strong. It’s relational. What makes it a spectrum is that some languages offer tools to help with conversions and changing of types on the fly. Some use things like pointers. This is why you may hear people saying that Java is more strongly typed than C or C++, when obviously C++ is strongly typed in comparison to JavaScript.

    I find it not so crucial to understand every nuance of what makes a language strong or weak. As long as you know some of the basics and can tell the difference between levels of strength, you’ll be in good shape when picking a language for a given project and its requirements.

    Choosing Which Style Fits Your Project

    There are many reasons why you might choose one language over another for your next project. Type systems tend to fall low on most people’s list, trumped by bigger considerations such:

    • the language a developer is most comfortable with
    • which language offers more features that fit the project scope
    • the tools that are available for faster development

    But when it comes to looking at type systems, keep in mind that if you’re working on a mission critical project that needs to be memory efficient, stringent, and where errors can be caught early, you might want to look at something statically typed. If the language shouldn’t make assumptions and requires explicit instructions to help with critical algorithms, also consider something that’s strongly typed. These are languages you tend to find in “AAA” rated games, for example.

    However, if you’re looking to get something out fast and with flexibility, which affords some expressiveness by the programmer, then dynamic or weak typed languages might be a better fit.

    Or you might prefer languages that mix the two. This is partly why a language like Python is chosen by many.

    Conclusion

    This article has attempted to cover the introductory differences between static and dynamic type systems and also the differences between strong/weak type systems. We’ve talked about how they compare, why you might choose one over the other, which languages fit into each of these systems, and how you might use these differences to choose the language for your next project.

    I hope you’ve found this article informative. If you take away only one thing from this article, let it be the idea that static doesn’t necessarily mean strong and dynamic doesn’t necessarily mean weak. Languages can exhibit various combinations of each. In the case of strong and weak typing, you can have varying degrees of strength in relation to one another.

    Good luck on your next project and thanks for reading!