<p dir="auto">Using TypeScript 1.7.3.</p>
<p dir="auto">Suppose I have the below npm packages.<br>
The declaration files are generated by TypeScript compiler, and referred to from the other packages by means of the way described <a href="https://github.com/Microsoft/TypeScript/wiki/Typings-for-npm-packages">here</a>.</p>
<h3 dir="auto">package-a</h3>
<p dir="auto">ts src:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="export default class ClassA {
  private foo: string;
  bar: number;
}"><pre class="notranslate"><span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-k">class</span> <span class="pl-smi">ClassA</span> <span class="pl-kos">{</span>
  <span class="pl-k">private</span> <span class="pl-c1">foo</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
  <span class="pl-c1">bar</span>: <span class="pl-smi">number</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">ts declaration:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare class ClassA {
  private foo;
  bar: number;
}
export default ClassA;"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">class</span> <span class="pl-smi">ClassA</span> <span class="pl-kos">{</span>
  <span class="pl-k">private</span> <span class="pl-c1">foo</span><span class="pl-kos">;</span>
  <span class="pl-c1">bar</span>: <span class="pl-smi">number</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-smi">ClassA</span><span class="pl-kos">;</span></pre></div>
<h3 dir="auto">package-b (depends on package-a):</h3>
<p dir="auto">ts src:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import ClassA from 'package-a';

namespace ClassAFactory {
  export function create(): ClassA {
    return new ClassA();
  }
}
export default ClassAFactory;"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-smi">ClassA</span> <span class="pl-k">from</span> <span class="pl-s">'package-a'</span><span class="pl-kos">;</span>

<span class="pl-k">namespace</span> <span class="pl-smi">ClassAFactory</span> <span class="pl-kos">{</span>
  <span class="pl-k">export</span> <span class="pl-k">function</span> <span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">ClassA</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-smi">ClassA</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>
<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-smi">ClassAFactory</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">ts declaration:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import ClassA from 'package-a';

declare namespace ClassAFactory {
  function create(): ClassA;
}
export default ClassAFactory;"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-smi">ClassA</span> <span class="pl-k">from</span> <span class="pl-s">'package-a'</span><span class="pl-kos">;</span>

<span class="pl-k">declare</span> <span class="pl-k">namespace</span> <span class="pl-smi">ClassAFactory</span> <span class="pl-kos">{</span>
  <span class="pl-k">function</span> <span class="pl-s1">create</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">ClassA</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-smi">ClassAFactory</span><span class="pl-kos">;</span></pre></div>
<h3 dir="auto">package-c (depends on package-a and package-b):</h3>
<p dir="auto">ts src:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import ClassA from 'package-a';
import ClassAFactory from 'package-b';

let classA: ClassA;
classA = ClassAFactory.create(); // error!!"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-smi">ClassA</span> <span class="pl-k">from</span> <span class="pl-s">'package-a'</span><span class="pl-kos">;</span>
<span class="pl-k">import</span> <span class="pl-smi">ClassAFactory</span> <span class="pl-k">from</span> <span class="pl-s">'package-b'</span><span class="pl-kos">;</span>

<span class="pl-k">let</span> <span class="pl-s1">classA</span>: <span class="pl-smi">ClassA</span><span class="pl-kos">;</span>
<span class="pl-s1">classA</span> <span class="pl-c1">=</span> <span class="pl-smi">ClassAFactory</span><span class="pl-kos">.</span><span class="pl-en">create</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// error!!</span></pre></div>
<p dir="auto">The last line causes an error during compilation:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="error TS2322: Type 'ClassA' is not assignable to type 'ClassA'.
Types have separate declarations of a private property 'foo'."><pre class="notranslate"><code class="notranslate">error TS2322: Type 'ClassA' is not assignable to type 'ClassA'.
Types have separate declarations of a private property 'foo'.
</code></pre></div>
<p dir="auto">When I remove the line <code class="notranslate">private foo;</code> from the declaration of package-a, TypeScript does not emit any error.<br>
However this workaround is a bit painful.</p>
<p dir="auto">I understand that exposing private properties to declaration is by design (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="52430000" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/1532" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/1532/hovercard" href="https://github.com/microsoft/TypeScript/issues/1532">#1532</a>).<br>
I think TypeScript should ignore private properties when compiling variable assignment.<br>
Or is there any better workaround for this?</p>
<p dir="auto">(This is rather difficult to search for so apologies in advance for duplicates.)</p>
<p dir="auto">TS lacks Java-like inner classes or package-scoped visibility which makes it cumbersome to encapsulate parent-children object relationship where the child needs to manipulate parent's internal datastructure. This is not only common in many complicated object graphs but also in OO designs where an object wants to issue a limited "handle"-like object that only implements a specific subset of features.</p>
<p dir="auto">Currently the use cases above can only be implemented by exposing the internal datasturectures to the "child" or handing out loads of lambdas. This adds more tight coupling.</p>
<p dir="auto">An good example is the API to remove of an <code class="notranslate">Element</code> in the DOM. Currently one have to call <code class="notranslate">parent.removeChild(child)</code> which is not only clumsy but also makes it difficult for the child to impose additional logic on the removal. Ideally, we'd want to have a <code class="notranslate">remove()</code> method on the child (like in jQuery) and make the <code class="notranslate">Node.removeChild()</code> method only visible to <code class="notranslate">Node</code> implementors.</p>
<p dir="auto">Proposed solution:</p>
<p dir="auto">Create a pseudo- or built-in decorator that accepts a list of types. Members decorated with this can only be accessed by types listed. Alternatively, can extend the <code class="notranslate">private</code> keyword to accept an argument list like <code class="notranslate">private (to A, B) name:type...</code></p>