NativeError: introduce a new UnknownError instead of current TypeError

Hi, the following are a short description about the proposal: using TypeError as the default is incorrect in some ways, a new UnknownError should be introduced here and let the TypeError only accept the type exceptions.

Details

See TypeError - JavaScript | MDN, it says:

The TypeError object represents an error when a value is not of the expected type.

This is inconsistent with the current ECMA262 spec's NativeError section, which uses the TypeError for default use case, that's confusion a little bit, for developers, they use it as type exceptions more often, therefore I propose that a new UnknownError is for the default case, and let the TypeError be the type expectations only.

Probably, OtherError would be more appropriate name than UnknownError.

That said, it seems harder to me to change ECMA262 (BC break, etc.) than to change MDN (and I’m indeed gonna improve the description of TypeError on MDN right now).

Yea, MDN is easier to update, however what this is going to fix the naming problem, it means that TypeError's name is not proper for the default case, BTW the OtherError looks good to me, either :)

Note: I think the community should always do the right thing, not the easy one to land IMO.

I’ve checked the uses of TypeError in old 3rd edition of ECMA262 (referenced in the MDN doc). At that time, TypeError was indeed used for type errors. In later editions, its use has manifestly expanded.

Instead of introducing a catch-all error class à la OtherError, it is probably more appropriate to identify the different uses of TypeError, and either introduce more precise error classes, or amend the description of TypeError to include those cases.

For example, one use of TypeError I’ve identified, is when attempting to change (modify, delete, ...) an immutable value (in 3rd edition, such an operation would typically be ignored without throwing), e.g.:

"use strict";
var o = { };
Object.defineProperty(o, 'x', { value: 1, configurable: false, writable: false });
delete o.x; // TypeError
o.x = 2; // TypeError

Instead of introducing a catch-all error class à la OtherError, it is probably more appropriate to identify the different uses of TypeError, and either introduce more precise error classes, or amend the description of TypeError to include those cases.

List all exceptions precisely is not an easy work, so at user-land, developer uses Error for this purpose, therefore what I want to fix actually is:

  1. precisely create a default class, maybe UnknownError, OtherError or NativeError.
  2. change the role of TypeError to be precise, namely handling the type expectations.

For example, one use of TypeError I’ve identified, is when attempting to change (modify, delete, ...) an immutable value

Once the above 2 things get solid, the example could be resolved as taking these invalid operator are type exceptions or throwing a default error class instance instead of TypeError.

In later editions, its use has manifestly expanded.

Is there more history about this expansion? Moreover, the error parts in ECMA262 spec are really confusion a bit to me and others, I'm very glad to make them more precise in some ways, that's what I wanna contribute to and why :p

When defineProperty throws because the property wasn’t writable or configurable, that’s actually a more defensible place for a TypeError than, for example, ‘x wasn’t instanceof SomeConstructor.’ It actually concerns an immutable, categorical characteristic of a value, which is untrue of many other places TypeErrors are thrown.

One difficulty here is that almost everyone employs a mental model of ‘type’ which doesn’t actually exist within the language — which is fine, and should even be encouraged to an extent, but you may find the edges of appropriate usage get fuzzy.

1 Like

A more example to show the inappropriate usage with TypeError:

It throws the error as the default case, and there are many cases in the web-bluetooth spec.

Noticed that MDN has updated its description about TypeError at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError, I'm fine with that, either :)

These appear to be algorithms for special conversion logic that can’t be expressed using Web IDL types alone. That happens pretty often (especially when dictionaries are involved). Like IDL’s own converter ops, such algorithms normally throw TypeErrors because they concern "converting user input to IDL values".

IDL does this even in some unintuitive cases, e.g. it mandates an ES number "3000" leads to a TypeError if passed where a range-enforced byte is expected, not a RangeError.

This pattern is common through platform APIs, rule of thumb being roughly ‘if user input does not meet expectations, throw a TypeError.’

In that specific example, the effect created is ‘at least one member of this dictionary is required.' That can’t be expressed in the dictionary definition itself, which can only say a member is or isn’t required individually, so custom conversion logic is introduced to take care of the rest.

I’m not clear on why you think the failure of input to meet specific shape criteria would be an inappropriate case for TypeError. If IDL dictionaries were expressive enough to allow declaring that constraint without custom operations, it would have definitely been one. (Also, it’s pretty important for platform specs to be consistent about this stuff and not go off on their own inventing new idioms.)