DEV Community

stereobooster
stereobooster

Posted on

Pragmatic types: is JavaScript an untyped language?

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.

source

There a lot of research on that matter:

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)

Collapse
 
codevault profile image
Sergiu Mureşan • Edited

Really great coverage of types!

There are also some issues when checking for booleans since:

if (someObj.isValid) { ... }

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 is true but if you are checking if someObj has the property isValid then this will return false when its value is either undefined or false so we would have to change our if condition:

if (someObj.isValid !== undefined) { ... }

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.

Collapse
 
stereobooster profile image
stereobooster

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.

Collapse
 
shalvah profile image
Shalvah • Edited

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?

Collapse
 
stereobooster profile image
stereobooster

Yes in JS coercion rules are pretty nasty

Collapse
 
stereobooster profile image
stereobooster

I wrote about untyped languages here