I would like to propose the addition of a new well-known Symbol:
This serves as a continuation of the discussion originally brought forward by Randy Buchholz here.
Most recently with
BigInt we've seen changes to the behavior of the
typeof operator. Looking at the past 5 or so years of standardization efforts, we've seen a total of two new primitive types (
bigint), and based on this history it is not unlikely that additional primitive Data Types and Values will be standardized and implemented in the future.
We've already seen tools like Babel transform
typeof UnaryExpressions into calls to a special helper function,
_typeof, that checks if the value if a polyfilled Symbol and makes sure to return
"symbol" rather than
"function" for it. This helper may be extended in the future to also handle
bigint, and other potential future primitive values. This is a user-land, syntax transformation-powered way to work around a limitation which is that there's no way to extend the runtime semantics of the
typeof operator. It can be avoided entirely with a Well-Known symbol such as
Symbol.typeofTag which polyfill writers may rely on for ensuring compatibility and test262 compliance.
Looking at the specification as it is today, the
InstanceOfOperator (12.10.4) uses the Well-Known symbol
Symbol.hasInstance to determine if a constructor object recognizes an object as one of the constructor's instances. This allows for tapping into the behavior of
instanceof. Because of this, I would argue that it makes just as much sense to extend the runtime semantics of the
typeof operator (12.5.5) to check for a handler for the Well-Known symbol
Symbol.typeofTag and call it if it exists, and otherwise fall back to Table 37. This would be backwards-compatible and wouldn't "break the web" .
Specifically, I suggest that the runtime semantics of the
typeof operator (12.5.5) would change to the following:
1. Let val be the result of evaluating UnaryExpression. 2. If Type(val) is Reference, then a. If IsUnresolvableReference(val) is true, return "undefined". 3. Set val to ? GetValue(val). 4. Let tag be ? Get(val, @@typeofTag). 5. If tag is not undefined, then a. Return ! ToString(tag). 6. Return a String according to Table 37.
Table 1 containing the Well-Known Symbols (22.214.171.124) would be extended with a new row:
|Specification Name||[[Description]]||Value and Purpose|
||A String valued property that is accessed with the typeof operator.|