# enum typeof

**URL:** <https://es.discourse.group/t/enum-typeof/1516>\
**Category:** 💡 Ideas\
**Created:** [November 10, 2022, 9:18pm UTC](https://es.discourse.group/t/enum-typeof/1516 "2022-11-10T21:18:53Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rudxain](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rudxain/32/2272_2.png) [@Rudxain](https://es.discourse.group/u/Rudxain)\
**Post date:** [November 10, 2022, 9:18pm UTC](https://es.discourse.group/t/enum-typeof/1516/1 "2022-11-10T21:18:54Z")

</div>

I'm aware that modern text editors, IDEs, linters, and even TypeScript itself already alleviate this issue considerably, but they don't _quite_ make it. I'm talking about `typeof x == STRING_LITERAL`, which is such a common idiom that VScode has autocompletion enabled for the `LITERAL` part.

I propose that JS should have an object or enum (this one is only valid if any of the enum proposals gets to Stage 4) that enumerates all possible values that `typeof` could return. A userland implementation would be:

```javascript
/**
 * Strings returned by `typeof`.
 * 
 * For the sake of conciseness, the property keys are shortened.
 * I would expect the keys to be equal to the values (only diff being capitalization).
 * @readonly
 * @enum {string}
 */
const TYPE = Object.freeze({
    OBJ: "object",
    UNDEF: "undefined",
    BOOL: "boolean",
    NUM: "number",
    BIGINT: "bigint",
    STR: "string",
    SYM: "symbol",
    FN: "function"
})

typeof isNaN == TYPE.FN //true

```

The problem is the prototype chain, so accessing arbitrary props can return proto-props. Using `Object.create(null)` and then assigning prevents static checking, so we can't use it. Using `Map` is not a good alternative, because `Map`s cannot be accessed using dot notation.

If this was provided as a library built-in, it would be future-proof, because if new types are added it would be auto-reflected on the enum.

`TYPE` doesn't need to be a global var, it could be set in an existing (or future) namespace, like `Enum`, or something else.

Another solution is to avoid strings altogether and use "raw enums", but that would require a new operator akin to `instanceof`, that compares enum values directly like this:

```javascript
0 typein Enum[Symbol.NUMBER] //true

```

I took inspiration from `Symbol.iterator`

Related: [Enums in Javascript with ES6 - Stack Overflow](https://stackoverflow.com/questions/44447847/enums-in-javascript-with-es6)

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [November 10, 2022, 9:48pm UTC](https://es.discourse.group/t/enum-typeof/1516/2 "2022-11-10T21:48:38Z")

</div>

We don’t have general purpose enum yet, but also, I’m not sure why this is a problem that needs solving. As you said, every tool in the ecosystem knows what the typeof values are - and someone not using these tools won’t get an error if they typo the enum property name, so it won’t help them.

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [November 11, 2022, 4:55am UTC](https://es.discourse.group/t/enum-typeof/1516/3 "2022-11-11T04:55:19Z")

</div>

> [@Rudxain](#):
>
> The problem is the prototype chain, so accessing arbitrary props can return proto-props. Using `Object.create(null)` and then assigning prevents static checking, so we can't use. Using `Map` is not a good alternative, because `Map`s cannot be accessed using dot notation.

You can set the prototype in line:

```javascript
const LR = Object.freeze({
   __proto__ : null,
   L: "left",
   R: "right",
});

```

---

<div class="post-metadata">

**Author:** ![Rudxain](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rudxain/32/2272_2.png) [@Rudxain](https://es.discourse.group/u/Rudxain)\
**Post date:** [November 11, 2022, 9:30pm UTC](https://es.discourse.group/t/enum-typeof/1516/4 "2022-11-11T21:30:36Z")

</div>

> [@ljharb](#):
>
> We don’t have general purpose enum yet

I know, that's why we would have to wait.

> [@ljharb](#):
>
> I’m not sure why this is a problem that needs solving

I think the most important advantage is runtime detection of available types. But that's usually unnecessary, because built-in types usually come with their own literals and syntax

```javascript

```

---

<div class="post-metadata">

**Author:** ![Rudxain](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rudxain/32/2272_2.png) [@Rudxain](https://es.discourse.group/u/Rudxain)\
**Post date:** [November 11, 2022, 9:32pm UTC](https://es.discourse.group/t/enum-typeof/1516/5 "2022-11-11T21:32:52Z")

</div>

> [@aclaymore](#):
>
> You can set the prototype in line

Thank you for the info. But, isn't ` __proto__ ` bad practice? I heard that it should be avoided, even if we're deleting it

---

<div class="post-metadata">

**Author:** ![senocular](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/senocular/32/642_2.png) [@senocular](https://es.discourse.group/u/senocular)\
**Post date:** [November 11, 2022, 11:23pm UTC](https://es.discourse.group/t/enum-typeof/1516/6 "2022-11-11T23:23:05Z")

</div>

There are two ` __proto__ `s. One is a legacy browser accessor property in `Object.prototype` which you shouldn't use, and then theres a special key in object initializers called ` __proto__ ` which will set the prototype of the object being created, but do so directly rather than going through the accessor. This key isn't triggered for computed properties, so if you ever want a property called `" __proto__"` you can still get one using a computed property within the initializer.

```javascript
const o1 = {
    __proto__ : { foo: true } // not the accessor
}
console.log(o1.hasOwnProperty(" __proto__")) // false
console.log(Object.getPrototypeOf(o1).hasOwnProperty("foo")) // true

const o2 = {
    [" __proto__"]: { foo: true }
}
console.log(o2.hasOwnProperty(" __proto__")) // true
console.log(Object.getPrototypeOf(o2).hasOwnProperty("foo")) // false

```

If after an object is created you refer to ` __proto__ ` it will be using the `Object.prototype` accessor (assuming you haven't given it its own ` __proto__ ` as seen in the second example above).

```javascript
const o = {}
o. __proto__ = { foo: true } // is the accessor
console.log(o1.hasOwnProperty(" __proto__")) // false
console.log(Object.getPrototypeOf(o1).hasOwnProperty("foo")) // true

```

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [November 12, 2022, 6:54am UTC](https://es.discourse.group/t/enum-typeof/1516/7 "2022-11-12T06:54:13Z")

</div>

IMO, the typeof operator is just broken. It treats "null" as type object, and it treats functions as a different type from objects (a function is an object, so it really doesn't make sense to have `typeof myFn === 'object'` not be true). Adding more features around this operator would just further establish its broken type-categorization system.

What I would really like to see, and [something that's been discussed a bit elsewhere](https://es.discourse.group/t/consider-adding-an-alternative-to-typeof-that-doesn-t-include-the-legacy-baggage-of-typeof/526/7), is for the language to add a replacement to the typeof operator. Perhaps, as part of that discussion, needs involving the ability to programmatically access the different available types without hard-coding a list of types can be addressed

Though... to be honest, I've never actually ran into a concrete use-case where having a way to programmatically get my hands on all of the possible outputs of typeof would be handy, so it's hard to picture the utility of that.

---

<div class="post-metadata">

**Author:** ![Rudxain](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rudxain/32/2272_2.png) [@Rudxain](https://es.discourse.group/u/Rudxain)\
**Post date:** [November 12, 2022, 6:51pm UTC](https://es.discourse.group/t/enum-typeof/1516/8 "2022-11-12T18:51:18Z")

</div>

> [@senocular](#):
>
> two ` __proto__ `s

Thanks for clarifying. That's seems like a very weird quirk of JS

---

<div class="post-metadata">

**Author:** ![Rudxain](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/rudxain/32/2272_2.png) [@Rudxain](https://es.discourse.group/u/Rudxain)\
**Post date:** [November 13, 2022, 4:19am UTC](https://es.discourse.group/t/enum-typeof/1516/9 "2022-11-13T04:19:22Z")

</div>

> [@theScottyJam](#):
>
> it treats functions as a different type from objects

TBF, functions are just "callable objs" which makes them "exotic" in a similar way to Arrays, but the fact that `typeof []` doesn't return "array" would make even less sense, so I agree with you, it's broken.

> [@theScottyJam](#):
>
> more features around this operator would just further establish its broken type-categorization system.

That's one of the reasons why I suggested `typein`

> [@theScottyJam](#):
>
> use-case where having a way to programmatically get my hands on all of the possible outputs of typeof

The only I can think of, right now, off the top of my head, would be when implementing a function that checks a predicate against an arbitrary numeric value (number, bigint, potentially bigdecimal), returning false for every non-numeric.

While `BigFloat`s/`BigDecimal`s are not implemented, a "normal" implementation of this fn would return `false` for bigfloats (when they get added), despite being numeric. But a future-proof generic fn implementation may detect the existence of `BigFloat`s at runtime and "behave properly".

But, of course, this fn can be implemented by just checking the existence of the corresponding global object. Neither global-objs nor type names are guaranteed to be the same in the future, so both approaches are equivalent... _unless,_ we had a "type category" function or operator to get the superset name of a subset type, allowing the fn to be **truly** future proof, because it'll work with whatever primitive numeric type that's added in the future, without need to update the code.

This is useful, because there's no way of knowing if a global object is associated with a primitive type, unless we use `typeof`:

```javascript
const f = x => {
  try {
    // I know fns aren't primitives
    const t = typeof x() 
    return t != 'object' ? t : undefined
  }
  catch (e) {
   //to-do
  }
}

```

(This reply is incomplete, I'll edit it later)  
(Edit: I forgot what I was going to say...)

---

<div class="post-metadata">

**Author:** ![jithujoshyjy](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/jithujoshyjy/32/399_2.png) [@jithujoshyjy](https://es.discourse.group/u/jithujoshyjy)\
**Post date:** [November 13, 2022, 12:24pm UTC](https://es.discourse.group/t/enum-typeof/1516/10 "2022-11-13T12:24:25Z")

</div>

Now that I think about it, is it a good idea to add a new method for this to the Reflect object;

I mean typeof it a way of Reflection, so in my opinion it makes sense.  
Something like

```javascript
Reflect.type(x) // not sure about the api

```

---

<div class="post-metadata">

**Author:** ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)\
**Post date:** [November 13, 2022, 1:49pm UTC](https://es.discourse.group/t/enum-typeof/1516/11 "2022-11-13T13:49:13Z")

</div>

The `Reflect` namespace represents the standard internal methods of objects that form JavaScript's meta-object-protocol. [ECMAScript® 2023 Language&nbsp;Specification](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-object-internal-methods-and-internal-slots)

Type is a more general operation not tied to objects, so it may not follow that it would live in the `Reflect` namespace.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [November 20, 2022, 1:37am UTC](https://es.discourse.group/t/enum-typeof/1516/13 "2022-11-20T01:37:42Z")

</div>

Not entirely sure what you mean? My understanding of generics is that they're a feature to aid users in creating "generic" type definitions that are capable of operating on various types. JavaScript doesn't have a concept of "type definitions". TypeScript has type definitions though, which is why TypeScript provides generic syntax.
