<p dir="auto">With the introduction of WeakMap, the JS runtime now has <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap#Description" rel="nofollow">restrictions</a> on where primitive types are disallowed. Is it possible (or planned) to have language support for discriminating from primitive types and the ability to constraint generic types based on that discrimination?</p>
<p dir="auto">From a <a href="http://stackoverflow.com/questions/28122754/discriminate-between-empty-object-type-and-other-concrete-types" rel="nofollow">previous SO post I made</a>, the answer seems to be "no". But taken in light of WeakMap requirements, perhaps it can be revisited?</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var a = 1;
undefined

var b = new Number(a);
undefined

var m = new WeakMap();
undefined

m.set(a, 1)
VM674:2 Uncaught TypeError: Invalid value used as weak map key
    at WeakMap.set (native)
    at &lt;anonymous&gt;:2:3
    at Object.InjectedScript._evaluateOn (&lt;anonymous&gt;:905:140)
    at Object.InjectedScript._evaluateAndWrap (&lt;anonymous&gt;:838:34)
    at Object.InjectedScript.evaluate (&lt;anonymous&gt;:694:21)(anonymous function) @ VM674:2InjectedScript._evaluateOn @ VM305:905InjectedScript._evaluateAndWrap @ VM305:838InjectedScript.evaluate @ VM305:694

m.set(b, 1)
WeakMap {Number {[[PrimitiveValue]]: 1} =&gt; 1}"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-c1">1</span><span class="pl-kos">;</span>
<span class="pl-c1">undefined</span>

<span class="pl-k">var</span> <span class="pl-s1">b</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Number</span><span class="pl-kos">(</span><span class="pl-s1">a</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c1">undefined</span>

<span class="pl-k">var</span> <span class="pl-s1">m</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">WeakMap</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-c1">undefined</span>

<span class="pl-s1">m</span><span class="pl-kos">.</span><span class="pl-en">set</span><span class="pl-kos">(</span><span class="pl-s1">a</span><span class="pl-kos">,</span> <span class="pl-c1">1</span><span class="pl-kos">)</span>
VM674:<span class="pl-c1">2</span> <span class="pl-v">Uncaught</span> TypeError: <span class="pl-v">Invalid</span> <span class="pl-s1">value</span> <span class="pl-s1">used</span> <span class="pl-k">as</span> <span class="pl-s1">weak</span> <span class="pl-s1">map</span> <span class="pl-s1">key</span>
    <span class="pl-s1">at</span> <span class="pl-v">WeakMap</span><span class="pl-kos">.</span><span class="pl-en">set</span> <span class="pl-kos">(</span><span class="pl-s1">native</span><span class="pl-kos">)</span>
    <span class="pl-s1">at</span> <span class="pl-c1">&lt;</span><span class="pl-s1">anonymous</span><span class="pl-c1">&gt;</span>:<span class="pl-c1">2</span>:<span class="pl-c1">3</span>
    <span class="pl-s1">at</span> <span class="pl-v">Object</span><span class="pl-kos">.</span><span class="pl-c1">InjectedScript</span><span class="pl-kos">.</span><span class="pl-c1">_evaluateOn</span> <span class="pl-kos">(</span><span class="pl-c1">&lt;</span><span class="pl-ent">anonymous</span><span class="pl-c1">&gt;</span>:905:140)
    at Object.InjectedScript._evaluateAndWrap (<span class="pl-c1">&lt;</span><span class="pl-ent">anonymous</span><span class="pl-c1">&gt;</span>:838:34)
    at Object.InjectedScript.evaluate (<span class="pl-c1">&lt;</span><span class="pl-ent">anonymous</span><span class="pl-c1">&gt;</span>:694:21)(anonymous function) @ VM674:2InjectedScript._evaluateOn @ VM305:905InjectedScript._evaluateAndWrap @ VM305:838InjectedScript.evaluate @ VM305:694

m.set(b, 1)
WeakMap <span class="pl-kos">{</span><span class="pl-v">Number</span> <span class="pl-kos">{</span><span class="pl-kos">[</span><span class="pl-kos">[</span><span class="pl-v">PrimitiveValue</span><span class="pl-kos">]</span><span class="pl-kos">]</span>: <span class="pl-c1">1</span><span class="pl-kos">}</span> <span class="pl-c1">=</span><span class="pl-c1">&gt;</span> <span class="pl-c1">1</span><span class="pl-kos">}</span></pre></div>
<h1 dir="auto">The <code class="notranslate">object</code> primitive type</h1>
<p dir="auto">This proposal describe a new primitive type for typescript <code class="notranslate">object</code>.</p>
<h2 dir="auto">Use case</h2>
<p dir="auto">JavaScript core api contains some functions that takes <code class="notranslate">object</code> as parameter :</p>
<ul dir="auto">
<li><code class="notranslate">Object.getPrototypeOf</code></li>
<li><code class="notranslate">Object.getOwnPropertyDescriptor</code></li>
<li><code class="notranslate">Object.create</code></li>
<li>...etc</li>
</ul>
<p dir="auto">Currently there is no way in typescript to prevent passing other primitive type (<code class="notranslate">string</code>, <code class="notranslate">number</code>, etc ...) to those functions.<br>
For example  <code class="notranslate">Object.create('string')</code> is a perfectly valid typescript statement, even if it will ends up with an error.<br>
Creating a new <code class="notranslate">object</code> primitive type would allows to model more correctly the signature of those function, and every function that share similar constraint.</p>
<h2 dir="auto">Type Checking</h2>
<h3 dir="auto">Assignability</h3>
<p dir="auto">The <code class="notranslate">object</code> type is the equivalent of <code class="notranslate">{}</code> minus the assignability of other basic type, that means that :</p>
<ul dir="auto">
<li>any other basic types are not assignable to <code class="notranslate">object</code></li>
<li>any non-basic type is assignable to <code class="notranslate">object</code></li>
<li>object is only assignable to <code class="notranslate">{}</code> and <code class="notranslate">any</code></li>
</ul>
<p dir="auto">This behavior is coherant to how javascript works, the type represent every value that respect the constraint <code class="notranslate">typeof value === 'object'</code> plus <code class="notranslate">undefined</code>.</p>
<h3 dir="auto">Type guard</h3>
<p dir="auto">A new type guard has to be introduced for <code class="notranslate">object</code> : <code class="notranslate">typeof value === 'object'</code>.<br>
Optionally the compiler could also accept comparaison with the <code class="notranslate">Object</code> function cast : <code class="notranslate">Object(value) === value</code>.</p>