Static typing is a programming language feature that requires you to strictly define the structure and data types of the code you write. While it’s often more work for the developer, it leads to much cleaner and understandable codebases in the long run.
What Is Static Typing?
In a dynamically typed language, you define everything with
var. There are no predefined types like
int; the variable simply contains a value:
var num = 5; var str = "hello";
This might not be an issue for local variables like this, but once you start working with more complex data, you start to hit a problem. Functions don’t give you any information about what arguments you should pass it, beyond the function names themselves. If you try to pass it junk arguments, it’ll accept them, and if the function’s code is expecting a string instead of a number, it may throw an error.
But, in a statically typed language like C#, the types are set before you hit compile. It’s immediately much more clear what the function wants from you, and if you try to pass it something it didn’t ask for, the compiler will throw an error.
Beyond that, it’s also much more clear what the function actually does, because the function will have a return type. Without prior understanding of the codebase, or even taking a single look at the source code, you can infer what it’s supposed to do from the return type, function name, and input parameters.
This static typing applies everywhere, and usually pretty aggressively. Anytime you define a variable, you must specify a type name. All functions must have fully specified type names for the arguments and return type. If you’re switching from dynamically typed languages, you won’t be allowed to just write
var without thinking.
Why Is Static Typing Useful?
If this seems like extra work, it certainly is. But it has some great benefits in the long run.
This helps catch errors early, and reduces the number of buggy commits your developers will be making.
Beyond catching errors in sloppy code, static typing can make up for the extra work by allowing you to code more efficiently in the future. Whenever you use a function, or try to access properties of a class, your IDE can go look up what types the function takes, or which methods the class implements. This makes working with code you didn’t write a lot easier.
Statically typed code can also run faster. It doesn’t matter if the language is interpreted or compiled; either way, knowledge of static types can allow for additional machine code optimization, so your program isn’t using more memory or clock cycles than it really needs.
Is There Any Reason to Prefer Dynamic Typing?
Because nothing is specified at compile time, dynamically typed languages often use duck typing to determine what an object can do. Checking if a method exists before calling it allows different kinds of input to be passed to the function, which can enable more flexible polymorphism.
Overall, it’s all personal preference, so it’s not possible to say that static typing is better all of the time. It comes down to you and your project’s needs, and also any other features of the languages you’re considering using.
Strongly Typed vs. Weakly Typed
Despite sounding very similar, “strongly vs. weakly typed” and “statically vs. dynamically typed” are two different concepts.
Strongly typed means that the language doesn’t do many implicit type conversions or type coercions. For example, C# is a strongly typed language. If you want to pass an
int to a function that expects a
float, you’ll get an error.
This can be fixed with an explicit conversion, called a cast. Strongly typed languages require more casts. Weakly typed languages will do automatic conversions. Again, it’s not black and white here, and some implicit conversions do exist in C# and other strongly typed languages, and you can define your own implicit conversions between custom types as well.
Generally, strong typing leads to less confusion overall, but implicit conversions where it makes sense are useful. For example, converting
float automatically is usually fine, as no data is changed beyond switching to a different type. Converting a
float to an
int would need some form of rounding to get rid of the decimal places.
Weak typing can lead to confusion in some extreme cases. For example, JS is famous for its generous implicit conversions: You can add a number to a string, and get a string as a result. But if you multiply a number and a string, it parses the string into a number, and returns
NaN if it can’t be parsed.