Brendan Eich (2013-07-28T18:23:03.000Z)
See http://www.slideshare.net/BrendanEich/value-objects (tweet: 
https://twitter.com/BrendanEich/status/360538755309912064), in 
particular slide 13:

"""
typeof travails and travesties

• Invariant -- these two imply each other in JS:
• typeof x == typeof y && x == y
• x === y
• 0m == 0 && 0L == 0 means 0m == 0L (transitivity), but 0m !== 0L 
(different precision and radix) so typeof 0m != typeof 0L per the invariant
• Usability favors typeof 0L == “int64” and typeof 0m == “decimal” anyway
• Making typeof extensible requires a per-realm registry with 
throw-on-conflict
"""

The appendix of this post proposes how to make typeof extensible, with 
throw-on-conflict in general. A special case for null allows

Function.setTypeOf(null, "null")

and

Function.setTypeOf(null, "object")

to be called multiple times per realm, so new code can opt into sane 
typeof null. The attempt to break compatibility for ES6 proposed at 
http://wiki.ecmascript.org/doku.php?id=harmony:typeof_null failed by 
being too web-incompatible, but given Function.setTypeOf for value 
objects, it's easy to support opt-in typeof repair.

I considered syntax instead of API:

typeof null = "null";

(i.e., heretofore illegal left-hand side expressions consisting of 
typeof unary expressions), but this fails to express the symmetric 
relationship when applied to value object constructors:

typeof bignum = "bignum";

does not match runtime sense of (typeof bignum), which must return 
"function". Instead,

Function.setTypeOf(bignum, "bignum")

works with minimal boilerplate (the .prototype is implicit for the first 
parameter) and the value-object-constructor-function-or-null leading 
parameter fits the Function-static namespacing.

As promised, other than when passing null as the first actual parameter, 
Function.setTypeOf throws on conflict.

Comments welcome.

/be

---- extensible typeof proposal ----

Per-real typeof customization API, for two use-cases:

* Value objects (http://www.slideshare.net/BrendanEich/value-objects)
* Opt-in typeof null fixing and unfixing.

Two Map instances, internal to the specification:
ExemplarToTypeofMap: object -> string
TypeofToExemplarMap: string -> object

New Function.setTypeOf static, a peer of Function.defineOperator:

Function.setTypeOf(V, U)

1. Let S = ToString(U)
2. Let T = V
3. If T is null then
3a. If S is not "null" and S is not "object", throw
4. Else
4a. If T is not a value object constructor, throw
4b. T = T.prototype
4c. If TypeofToExemplarMap.has(S), throw
5. Call TypeofToExemplarMap.set(S, T)
6. Call ExemplarToTypeofMap.set(T, S)

 From the draft ES6 spec:

11.4.3 The typeof Operator

from Table 31:
+-----------------------+------------------------------------------------+
| ... : ... |
+-----------------------+------------------------------------------------+
| Null | ExemplarToTypeofMap.has(val) |
| | ? ExemplarToTypeofMap.get(val) |
| | : "object" |
+-----------------------+------------------------------------------------+
| ... : ... |
+-----------------------+------------------------------------------------+
| Object (value object) | ExemplarToTypeofMap.has(val) |
| | ? ExemplarToTypeofMap.get(val.[[Prototype]]) |
| | : "object" |
+-----------------------+------------------------------------------------+

Notes:

* "is (not) a value object constructor" and "(is a) value object" TBD
* Value objects are non-extensible so their [[Prototype]] can't change
domenic at domenicdenicola.com (2013-08-12T05:16:14.316Z)
See http://www.slideshare.net/BrendanEich/value-objects (tweet: 
https://twitter.com/BrendanEich/status/360538755309912064), in 
particular slide 13:

---

# typeof travails and travesties

- Invariant -- these two imply each other in JS:
- `typeof x == typeof y && x == y`
- `x === y`
- `0m == 0 && 0L == 0` means `0m == 0L` (transitivity), but `0m !== 0L` (different precision and radix) so `typeof 0m != typeof 0L` per the invariant
- Usability favors `typeof 0L == "int64"` and `typeof 0m == "decimal"` anyway
- Making `typeof` extensible requires a per-realm registry with throw-on-conflict

---

The appendix of this post proposes how to make typeof extensible, with 
throw-on-conflict in general. A special case for null allows

```js
Function.setTypeOf(null, "null")
```

and

```js
Function.setTypeOf(null, "object")
```

to be called multiple times per realm, so new code can opt into sane 
typeof null. The attempt to break compatibility for ES6 proposed at 
http://wiki.ecmascript.org/doku.php?id=harmony:typeof_null failed by 
being too web-incompatible, but given `Function.setTypeOf` for value 
objects, it's easy to support opt-in typeof repair.

I considered syntax instead of API:

```js
typeof null = "null";
```

(i.e., heretofore illegal left-hand side expressions consisting of 
typeof unary expressions), but this fails to express the symmetric 
relationship when applied to value object constructors:

```js
typeof bignum = "bignum";
```

does not match runtime sense of `(typeof bignum)`, which must return 
`"function"`. Instead,

```js
Function.setTypeOf(bignum, "bignum")
```

works with minimal boilerplate (the `.prototype` is implicit for the first 
parameter) and the value-object-constructor-function-or-null leading 
parameter fits the Function-static namespacing.

As promised, other than when passing null as the first actual parameter, 
`Function.setTypeOf` throws on conflict.

Comments welcome.

# extensible typeof proposal

Per-real typeof customization API, for two use-cases:

* Value objects (http://www.slideshare.net/BrendanEich/value-objects)
* Opt-in typeof null fixing and unfixing.

Two Map instances, internal to the specification:

- ExemplarToTypeofMap: object -> string
- TypeofToExemplarMap: string -> object

New `Function.setTypeOf` static, a peer of `Function.defineOperator`:

```js
Function.setTypeOf(V, U)
```

```
1. Let S = ToString(U)
2. Let T = V
3. If T is null then
3a. If S is not "null" and S is not "object", throw
4. Else
4a. If T is not a value object constructor, throw
4b. T = T.prototype
4c. If TypeofToExemplarMap.has(S), throw
5. Call TypeofToExemplarMap.set(S, T)
6. Call ExemplarToTypeofMap.set(T, S)
```

From the draft ES6 spec:

```
11.4.3 The typeof Operator

from Table 31:
+-----------------------+------------------------------------------------+
| ... : ... |
+-----------------------+------------------------------------------------+
| Null | ExemplarToTypeofMap.has(val) |
| | ? ExemplarToTypeofMap.get(val) |
| | : "object" |
+-----------------------+------------------------------------------------+
| ... : ... |
+-----------------------+------------------------------------------------+
| Object (value object) | ExemplarToTypeofMap.has(val) |
| | ? ExemplarToTypeofMap.get(val.[[Prototype]]) |
| | : "object" |
+-----------------------+------------------------------------------------+
```

Notes:

* "is (not) a value object constructor" and "(is a) value object" TBD
* Value objects are non-extensible so their [[Prototype]] can't change