Reflect.type

# Alexander Jones (10 years ago)

Just an idea, if it doesn't already exist somewhere.

Reflect.type(x) would match the spec's Type(x) function, in that it would basically be a better, more convenient typeof, i.e.

Reflect.types = {
    undefined: Symbol(),
    null: Symbol(),
    boolean: Symbol(),
    string: Symbol(),
    symbol: Symbol(),
    number: Symbol(),
    object: Symbol(),
}

Reflect.type(null) === Reflect.types.null
Reflect.type(function() {}) === Reflect.types.object

We weren't able to fix typeof null in harmony, but this seems like a good opportunity to introduce something new. Haven't thought about the repercussions of future support for new value types...

Any thoughts?

# Andrea Giammarchi (10 years ago)

FWIW, I think whatever contains "type" in modern JS should consider int32, float64, and all TypedArrays plus it would be awesome to have a way to define own types.

In any case, if your idea will be implemented, I think it should have named Symbols for debugging sake.

Symbol('undefined'),
Symbol('null'),
Symbol('boolean')

This would be at least consistent with current implementations of Symbol.iterator and friends.

Best

# Alexander Jones (10 years ago)

I'm sure there will evolve some other nomenclature for that in due course.

From www.slideshare.net/BrendanEich/value-objects2 it sounds as if

it would be reasonable to define Type(x) to be Value, and thus Reflect.type(x) to be Reflect.types.value.

Agree with the Symbol labels.

# Alexander Jones (9 years ago)

I've written this up as a strawman. It's available at alex-weej/es

# Alexander Jones (9 years ago)

For some strange reason esdiscuss.org has garbled that link! For the benefit of those readers:

alex-weej/es-reflect-type-proposal

(Apologies for spam)

# Alexander Jones (9 years ago)

How might I find a champion for this? Any takers here?

# Thaddee Tyl (9 years ago)

You suggest a list of types of fixed size. The lack of exposition of user-definable value types is a problem you mention.

Having a better typeof is not as useful as having a better instanceof.

This would be more valuable:

isA(42, Number) === true  // Doesn't work with instanceof
isA([1,3], Array) === true  // Does work with instanceof
isA({one:1}, Object) === true  // The distinction between array and
object was always weird with typeof
class Thing {}
isA(new Thing, Thing) === true
class SubThing {}
isA(new SubThing, Thing) === true  // Detects subclassing / prototype
chain (which instanceof does not do)

JS needs Ruby's is_a?.

# Jordan Harband (9 years ago)

How would your isA work across realms, taking a built-in constructor? [1,2] instanceof Array does not, which is why Array.isArray exists. Object(42) instanceof Number would have the same problem.

if class SubThing extends Thing {}, then new SubThing instanceof Thing would be true.

Based on your isA examples, Object(foo) instanceof bar should be reliable within a single realm, and works everywhere, without the need for a new builtin method.

# Thaddee Tyl (9 years ago)

On Sat, Jun 6, 2015 at 6:23 PM, Jordan Harband <ljharb at gmail.com> wrote:

if class SubThing extends Thing {}, then new SubThing instanceof Thing would be true.

Ah! Good. I expected it to fail just like this:

function Thing(){}
function SubThing(){}
SubThing.prototype = Object.create(Thing)
SubThing.prototype.constructor = Thing
Object(new SubThing) instanceof Thing  // false

Based on your isA examples, Object(foo) instanceof bar should be reliable within a single realm, and works everywhere, without the need for a new builtin method.

I can't think of a way to make something work across realms, so that's indeed the best we have got.

# Nick Krempel (9 years ago)

On 8 June 2015 at 15:05, Thaddee Tyl <thaddee.tyl at gmail.com> wrote:

Ah! Good. I expected it to fail just like this:

function Thing(){}
function SubThing(){}
SubThing.prototype = Object.create(Thing)  // BUG:
Object.create(Thing.prototype) intended?
SubThing.prototype.constructor = Thing
Object(new SubThing) instanceof Thing  // Then this would be true.

That only fails because of the probable bug on the third line.

# Thaddee Tyl (9 years ago)

On Mon, Jun 8, 2015 at 4:38 PM, Nick Krempel <ndkrempel at google.com> wrote:

On 8 June 2015 at 15:05, Thaddee Tyl <thaddee.tyl at gmail.com> wrote:

Ah! Good. I expected it to fail just like this:

function Thing(){}
function SubThing(){}
SubThing.prototype = Object.create(Thing)  // BUG:
Object.create(Thing.prototype) intended?
SubThing.prototype.constructor = Thing
Object(new SubThing) instanceof Thing  // Then this would be true.

That only fails because of the probable bug on the third line.

You're right. Sorry.

So, what is left? Is Reflect.type useful? Adding Undefined and Null as types for which Object(null) instanceof Null etc. seems unnecessary, since we'd use triple-equal comparison.

# Alexander Jones (9 years ago)

Such approach would Break the Web(tm), so it's not really an option anyway.

Reflect.type is really just a way to expose a concept inherent in the language which is already reified in the specification. It does not preclude future further type mechanisms that might prove more useful. "Don't let best be the enemy of better"!