I've found that some people call JavaScript a "dynamically, weakly typed" language, but some even say "untyped"? Which is it really?
-- https://stackoverflow.com/questions/964910/is-javascript-an-untyped-language
To answer the question we need to define what is "untyped", what is "dynamically" and "weakly" typed languages are - read the full post on the subject "Dynamically-, statically-, gradually-, weakly-, strongly- and un-typed languages". If you decided to skip it:
- Untyped - language with one type, like assembly language which works with the only one type - bit strings.
- Dynamically typed or better to say dynamically-checked types - language in which types get checked at runtime.
- Weakly typed - this term doesn't have an exact meaning, so I advise to avoid it, but most likely people refer to JavaScript's implicit coercions, which make types look "weak".
JS and types
There are seven possible values that typeof
returns: "number," "string," "boolean," "object," "function," "undefined," and "unknown". Also, we can check if values are an instance of some type like this:
date instanceof Date
or like this
Object.prototype.toString.call(date) === '[object Date]'
No, JS is not untyped. It has more than one type.
Is JavaScript a dynamically typed language?
Type checking "performed by system" at runtime:
undefined()
VM308:1 Uncaught TypeError: undefined is not a function
at <anonymous>:1:1
Type checking "performed by programmer" at runtime:
if (typeof x === "string")
Yes, JS is dynamically typed.
Why people get so confused about this subject?
JS goes an extra mile to pretend it doesn't have types or type errors.
What type errors exist in JS?
When you try to use non-function value as a function
undefined()
VM308:1 Uncaught TypeError: undefined is not a function
at <anonymous>:1:1
When you try to access a property of undefined
or null
value.
Other values considered to be an object and if you access an inexisting value of an object you will get undefined
instead of type error. This is hidden type error.
null.test
VM84:1 Uncaught TypeError: Cannot read property 'test' of null
at <anonymous>:1:1
undefined.test
VM134:1 Uncaught TypeError: Cannot read property 'test' of undefined
at <anonymous>:1:1
Arithmetic operations on non-number values result in NaN
, which is the JS way to express TypeErrors about arithmetic operations
1 * {}
NaN
Coercion
Coercion can be convenient when you do not need explicitly convert from integers to floating point numbers in arithmetic operations, but in JS coercion used to hide type errors.
1*"1" // result 1, should be type error
1+"1" // result "11", should be type error
1*[] // result 0, should be type error
1+[] // result "1", should be type error
"1"+[] // result "1", should be type error
JS tries to hide type errors so hard, that it resulted in obscure coercion rules.
There a lot of research on that matter:
- Wat, A lightning talk by Gary Bernhardt from CodeMash 2012. About coercions in JS
- WTFJS, 2012; github repo
- What the... JavaScript?, 2015; github repo
Inconsistent types
JS have bugs in type operators which are preserved until now for compatibility reasons. For example:
typeof null
"object"
typeof document.all
"undefined"
Bugs in type operators and obscure coercion rules make an impression that there is no way such language have types.
Final conclusion
JS has types, JS has type errors even so it tries to hide most of them, JS can check types at runtime. JS is dynamically typed language.
This post is part of the series. Follow me on twitter and github.
Top comments (6)
Really great coverage of types!
There are also some issues when checking for booleans since:
Works fine, but depends what you really mean by this condition. If you are checking the actual value of
someObj.isValid
this will enter the if block only if it istrue
but if you are checking ifsomeObj
has the propertyisValid
then this will return false when its value is eitherundefined
orfalse
so we would have to change our if condition:This might be bad practice (correct me if that's the case), but for a beginner it is hard to understand why you need that. Especially if
isValid
is an array or string.Good reminder. Type systems can protect against it. In terms of Flow it is called "sketchy" values. I need to write a small post about it.
Yeah, I think one of the greatest errors in the language's design was choosing to make invalid math operations return NaN rather than throw an exception. Nine times out of ten, programmers don't intend to multiply 3 by "five", so why not fail immediately and loudly?
Yes in JS coercion rules are pretty nasty
I wrote about untyped languages here