<p dir="auto"><strong>TypeScript Version:</strong></p>
<p dir="auto">1.8.10</p>
<h2 dir="auto">Problem</h2>
<p dir="auto">Sometimes we want to opt-out strict object literal check for a specific property. Some types have large amount or even unlimited number of properties, and we only want to model the most frequently used ones. However when we do use an unmodeled property in an object literal, the compiler  complains. E.g.:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface AttrBag {
  id?: string;
  style?: string;
  title?: string;
  'class'?: string;
}

function setAttrs(el: Element, attrs: AttrBag) {
  //...
}

setAttrs(document.createElement('a'), {
  title: 'foo', 
  href: 'bar', // error
  'data-x': 'y', //error
});"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-smi">AttrBag</span> <span class="pl-kos">{</span>
  <span class="pl-c1">id</span>?: <span class="pl-smi">string</span><span class="pl-kos">;</span>
  <span class="pl-c1">style</span>?: <span class="pl-smi">string</span><span class="pl-kos">;</span>
  <span class="pl-c1">title</span>?: <span class="pl-smi">string</span><span class="pl-kos">;</span>
  <span class="pl-s">'class'</span>?: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">function</span> <span class="pl-en">setAttrs</span><span class="pl-kos">(</span><span class="pl-s1">el</span>: <span class="pl-smi">Element</span><span class="pl-kos">,</span> <span class="pl-s1">attrs</span>: <span class="pl-smi">AttrBag</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-c">//...</span>
<span class="pl-kos">}</span>

<span class="pl-en">setAttrs</span><span class="pl-kos">(</span><span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'a'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-s">'foo'</span><span class="pl-kos">,</span> 
  <span class="pl-c1">href</span>: <span class="pl-s">'bar'</span><span class="pl-kos">,</span> <span class="pl-c">// error</span>
  <span class="pl-s">'data-x'</span>: <span class="pl-s">'y'</span><span class="pl-kos">,</span> <span class="pl-c">//error</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<h2 dir="auto">Existing solutions</h2>
<p dir="auto">Existing solutions have some limitations:</p>
<ul dir="auto">
<li>Add a type assertion for the object literal. This turns off object literal check entirely, which is undesirable, e.g.:</li>
</ul>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="setAttrs(document.createElement('a'), {
  titile: 'foo', // typo, but no error
  href: 'bar',
  'data-x': 'y',
} as AttrBag);"><pre class="notranslate"><span class="pl-en">setAttrs</span><span class="pl-kos">(</span><span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'a'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">titile</span>: <span class="pl-s">'foo'</span><span class="pl-kos">,</span> <span class="pl-c">// typo, but no error</span>
  <span class="pl-c1">href</span>: <span class="pl-s">'bar'</span><span class="pl-kos">,</span>
  <span class="pl-s">'data-x'</span>: <span class="pl-s">'y'</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span> <span class="pl-k">as</span> <span class="pl-smi">AttrBag</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<ul dir="auto">
<li>Augument the interface for all used properties. This is heavy weight for infrequently used properties; and more importantly, the effect is usually global and can't be undone in a specific source file.</li>
</ul>
<h2 dir="auto">Proposed solution: "additional property" modifier</h2>
<p dir="auto">If a property name in a object literal is modified with <code class="notranslate">+</code> ("additional property" modifier), and it doesn't exist in the target type, compiler should skip strict object literal check for this property, and treat this property as optional. E.g.:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="setAttrs(document.createElement('a'), {
  title: 'foo', 
  +href: 'bar', // OK
  +'data-x': 'y', // OK
});

// The type of attrs is { title: string, href?: string, 'data-x'?: string }
var attrs = {
  title: 'foo', 
  +href: 'bar',
  +'data-x': 'y',
};

attrs = {  // OK
  title: 'bar',
};"><pre class="notranslate"><span class="pl-en">setAttrs</span><span class="pl-kos">(</span><span class="pl-smi">document</span><span class="pl-kos">.</span><span class="pl-en">createElement</span><span class="pl-kos">(</span><span class="pl-s">'a'</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-s">'foo'</span><span class="pl-kos">,</span> 
  <span class="pl-c1">+</span><span class="pl-c1">href</span>: <span class="pl-s">'bar'</span><span class="pl-kos">,</span> <span class="pl-c">// OK</span>
  <span class="pl-c1">+</span><span class="pl-s">'data-x'</span>: <span class="pl-s">'y'</span><span class="pl-kos">,</span> <span class="pl-c">// OK</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-c">// The type of attrs is { title: string, href?: string, 'data-x'?: string }</span>
<span class="pl-k">var</span> <span class="pl-s1">attrs</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>
  <span class="pl-c1">title</span>: <span class="pl-s">'foo'</span><span class="pl-kos">,</span> 
  <span class="pl-c1">+</span><span class="pl-c1">href</span>: <span class="pl-s">'bar'</span><span class="pl-kos">,</span>
  <span class="pl-c1">+</span><span class="pl-s">'data-x'</span>: <span class="pl-s">'y'</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-s1">attrs</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span>  <span class="pl-c">// OK</span>
  <span class="pl-c1">title</span>: <span class="pl-s">'bar'</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">If there's a decorator that takes all optional parameters it's easy to mistake and write</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@decorator class A {}"><pre class="notranslate"><code class="notranslate">@decorator class A {}
</code></pre></div>
<p dir="auto">instead of</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@decorator() class A {}"><pre class="notranslate"><code class="notranslate">@decorator() class A {}
</code></pre></div>
<p dir="auto">The problem is that there's no warning and the decorator function does not get called at all.</p>
<p dir="auto">I suggest to make the parameterless version <code class="notranslate">@decorator</code> to be the same thing of <code class="notranslate">@decorator()</code>, thus avoiding confusion.</p>