<p dir="auto">Hello,</p>
<p dir="auto">I didn't find a previous discussion about this subject.<br>
Here is the code:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Class Test {
    private _test:string;
    public test:number;

    constructor() {
         this._test=&quot;&quot;;
         this.test=1;
         this.test2=&quot;&quot;;  // error: must be declared, but it should guess the typing is string and public
         this._test3 : string[]; // invalid for now: could be private string[]
         this.test4 : string[];  // invalid for now: could be public string[]
        private this.test5 : string[];  // invalid for now: could be public string[], but modified to private
     }
}"><pre class="notranslate"><code class="notranslate">Class Test {
    private _test:string;
    public test:number;

    constructor() {
         this._test="";
         this.test=1;
         this.test2="";  // error: must be declared, but it should guess the typing is string and public
         this._test3 : string[]; // invalid for now: could be private string[]
         this.test4 : string[];  // invalid for now: could be public string[]
        private this.test5 : string[];  // invalid for now: could be public string[], but modified to private
     }
}
</code></pre></div>
<p dir="auto">Do you plan to  support such a feature ? I mean this._test3,this.test4 and this.test5<br>
Are you working on this.test2 to add better intellisense for both ts and js (this.test2 shows any in vscode) ?</p>
<p dir="auto">Thanks in advance for your answers.</p>
<p dir="auto"><strong>Problem Statement:</strong> In TypeScript 1.1, there are two basic ways to initialize complex properties with strong typing via a parameterized class constructor.  Both have disadvantages.  I will illustrate this with a simple example that uses Knockout, but this issue applies to any other JavaScript library that implements complex objects via initializer functions.</p>
<p dir="auto"><strong>"Method 1"</strong> is to instantiate the properties outside of the constructor using a throw-away value, and then to set the desired value inside the constructor (see <code class="notranslate">RightTriangle1</code> below).  This method has the advantage of being rather simple to program/maintain because TypeScript automatically infers the property's type.  However, this has the potential to cause ripple effects or performance issues at runtime because the code to instantiate each property is run at least twice.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class RightTriangle1 {
    public height = ko.observable(0);
    public width = ko.observable(0);
    public hypotenuse = ko.computed(() =&gt; {
        console.log(&quot;hypotenuse 1 calculated&quot;);
        return Math.sqrt(this.height() * this.height() + this.width() * this.width());
    });
    constructor(height: number, width: number) {
        this.height(height);
        this.width(width);
    }
}
var rt1 = new RightTriangle1(3, 4);
console.log(&quot;hypotenuse 1: &quot; + rt1.hypotenuse());  // 5"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">RightTriangle1</span> <span class="pl-kos">{</span>
    <span class="pl-k">public</span> <span class="pl-c1">height</span> <span class="pl-c1">=</span> <span class="pl-s1">ko</span><span class="pl-kos">.</span><span class="pl-en">observable</span><span class="pl-kos">(</span><span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">public</span> <span class="pl-c1">width</span> <span class="pl-c1">=</span> <span class="pl-s1">ko</span><span class="pl-kos">.</span><span class="pl-en">observable</span><span class="pl-kos">(</span><span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-k">public</span> <span class="pl-c1">hypotenuse</span> <span class="pl-c1">=</span> <span class="pl-s1">ko</span><span class="pl-kos">.</span><span class="pl-en">computed</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"hypotenuse 1 calculated"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-k">return</span> <span class="pl-smi">Math</span><span class="pl-kos">.</span><span class="pl-en">sqrt</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">height</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">*</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">height</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">width</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">*</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">width</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-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">height</span>: <span class="pl-smi">number</span><span class="pl-kos">,</span> <span class="pl-s1">width</span>: <span class="pl-smi">number</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">height</span><span class="pl-kos">(</span><span class="pl-s1">height</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">width</span><span class="pl-kos">(</span><span class="pl-s1">width</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">var</span> <span class="pl-s1">rt1</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">RightTriangle1</span><span class="pl-kos">(</span><span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-c1">4</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"hypotenuse 1: "</span> <span class="pl-c1">+</span> <span class="pl-s1">rt1</span><span class="pl-kos">.</span><span class="pl-en">hypotenuse</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>  <span class="pl-c">// 5</span></pre></div>
<p dir="auto"><em>Knockout happens to have an advanced feature to defer execution of a computed, but that's beside the point.  Other libraries may not support such a feature and it's just one more thing for the developer to keep track of.</em></p>
<p dir="auto"><strong>"Method 2"</strong> is to <em>declare</em> the properties with an explicit type outside of the constructor, and then to <em>instantiate</em> them inside the constructor (see <code class="notranslate">RightTriangle2</code> below).  This method has the advantage of eliminating the runtime double-instantiation issue, but it <em>also</em> eliminates the convenience of having TypeScript infer the types.</p>
<p dir="auto">Method 2 has the drawback of extra work if a type is ever changed, but much worse than that, it places the burden on the developer to figure out <em>what the type of each member should be</em>.  For trivial members (string, number, etc.) or libraries you've written yourself, this is merely busy-work, however for complex types used by a JavaScript library it is sometimes difficult to determine unless the developer is quite familiar with the library's definition.  Lastly, this is just the sort of syntax that would make a JavaScript developer who was new to TypeScript think, <em>"This is exactly what I was afraid of!  Look at all that extra code I'm forced to write that just gets thrown away in the end!"</em></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class RightTriangle2 {
    public height : KnockoutObservable&lt;number&gt;;
    public width: KnockoutObservable&lt;number&gt;;
    public hypotenuse: KnockoutComputed&lt;number&gt;;
    constructor(height: number, width: number) {
        this.height = ko.observable(height);
        this.width = ko.observable(width);
        this.hypotenuse = ko.computed(() =&gt; {
            console.log(&quot;hypotenuse 2 calculated&quot;);
            return Math.sqrt(this.height() * this.height() + this.width() * this.width());
        });
    }
}
var rt2 = new RightTriangle2(6, 8);
console.log(&quot;hypotenuse 2: &quot; + rt2.hypotenuse()); // 10"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">RightTriangle2</span> <span class="pl-kos">{</span>
    <span class="pl-k">public</span> <span class="pl-c1">height</span> : <span class="pl-smi">KnockoutObservable</span><span class="pl-kos">&lt;</span><span class="pl-smi">number</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>
    <span class="pl-k">public</span> <span class="pl-c1">width</span>: <span class="pl-smi">KnockoutObservable</span><span class="pl-kos">&lt;</span><span class="pl-smi">number</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>
    <span class="pl-k">public</span> <span class="pl-c1">hypotenuse</span>: <span class="pl-smi">KnockoutComputed</span><span class="pl-kos">&lt;</span><span class="pl-smi">number</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">height</span>: <span class="pl-smi">number</span><span class="pl-kos">,</span> <span class="pl-s1">width</span>: <span class="pl-smi">number</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">height</span> <span class="pl-c1">=</span> <span class="pl-s1">ko</span><span class="pl-kos">.</span><span class="pl-en">observable</span><span class="pl-kos">(</span><span class="pl-s1">height</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">width</span> <span class="pl-c1">=</span> <span class="pl-s1">ko</span><span class="pl-kos">.</span><span class="pl-en">observable</span><span class="pl-kos">(</span><span class="pl-s1">width</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">hypotenuse</span> <span class="pl-c1">=</span> <span class="pl-s1">ko</span><span class="pl-kos">.</span><span class="pl-en">computed</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
            <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"hypotenuse 2 calculated"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-k">return</span> <span class="pl-smi">Math</span><span class="pl-kos">.</span><span class="pl-en">sqrt</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">height</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">*</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">height</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">width</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">*</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">width</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-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>
<span class="pl-k">var</span> <span class="pl-s1">rt2</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">RightTriangle2</span><span class="pl-kos">(</span><span class="pl-c1">6</span><span class="pl-kos">,</span> <span class="pl-c1">8</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"hypotenuse 2: "</span> <span class="pl-c1">+</span> <span class="pl-s1">rt2</span><span class="pl-kos">.</span><span class="pl-en">hypotenuse</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 10</span></pre></div>
<p dir="auto">In summary of the problem, "Method 1" begs performance or logic problems, and "Method 2" is too wordy.</p>
<p dir="auto"><strong>Proposal: "Method 3"</strong> Fairly early on in the public life of TypeScript, the team added the ability to indicate retained fields by placing visibility modifiers on constructor parameters.  This feature is awesome, but it only helps with trivial properties.  I would like to propose adding a new feature to TypeScript to allow this idiom within the <em>body</em> of a constructor as well.  This would permit compiling the code in the <code class="notranslate">RightTriangle3</code> example below.  <em>Note the public modifiers on height, width, and hypotenuse.</em></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class RightTriangle3 {
    constructor(height: number, width: number) {
        public this.height = ko.observable(height);
        public this.width = ko.observable(width);
        public this.hypotenuse = ko.computed(() =&gt; {
            console.log(&quot;hypotenuse 3 calculated&quot;);
            return Math.sqrt(this.height() * this.height() + this.width() * this.width());
        });
    }
}
var rt3 = new RightTriangle3(9, 12);
console.log(&quot;hypotenuse 3: &quot; + rt3.hypotenuse()); // 15"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">RightTriangle3</span> <span class="pl-kos">{</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">height</span>: <span class="pl-smi">number</span><span class="pl-kos">,</span> <span class="pl-s1">width</span>: <span class="pl-smi">number</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">public</span> <span class="pl-s1">this</span><span class="pl-kos">.</span><span class="pl-c1">height</span> <span class="pl-c1">=</span> <span class="pl-s1">ko</span><span class="pl-kos">.</span><span class="pl-en">observable</span><span class="pl-kos">(</span><span class="pl-s1">height</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">public</span> <span class="pl-s1">this</span><span class="pl-kos">.</span><span class="pl-c1">width</span> <span class="pl-c1">=</span> <span class="pl-s1">ko</span><span class="pl-kos">.</span><span class="pl-en">observable</span><span class="pl-kos">(</span><span class="pl-s1">width</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-s1">public</span> <span class="pl-s1">this</span><span class="pl-kos">.</span><span class="pl-c1">hypotenuse</span> <span class="pl-c1">=</span> <span class="pl-s1">ko</span><span class="pl-kos">.</span><span class="pl-en">computed</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
            <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"hypotenuse 3 calculated"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
            <span class="pl-k">return</span> <span class="pl-smi">Math</span><span class="pl-kos">.</span><span class="pl-en">sqrt</span><span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">height</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">*</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">height</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">+</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">width</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">*</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">width</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-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>
<span class="pl-k">var</span> <span class="pl-s1">rt3</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">RightTriangle3</span><span class="pl-kos">(</span><span class="pl-c1">9</span><span class="pl-kos">,</span> <span class="pl-c1">12</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">"hypotenuse 3: "</span> <span class="pl-c1">+</span> <span class="pl-s1">rt3</span><span class="pl-kos">.</span><span class="pl-en">hypotenuse</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// 15</span></pre></div>
<p dir="auto">With this proposal:</p>
<ul dir="auto">
<li>There are no breaking changes; code that compiled in TypeScript 1.0 works without any modification in this proposed future version.</li>
<li>The <code class="notranslate">RightTriangle3</code> class would have the <em>identical</em> JavaScript emit as <code class="notranslate">RightTriangle2</code>.</li>
<li>The <code class="notranslate">RightTriangle3</code> TypeScript compile-time type interface would <em>also be identical</em> to <code class="notranslate">RightTriangle2</code>.</li>
<li>The developer is not required to separate the declaration of the property from its instantiation just to get strong typing when using a parameterized constructor.</li>
<li>The developer is not required to update the type of a property if the class interface ever changes - they can just update the initializer code.</li>
<li>The TypeScript code in <code class="notranslate">RightTriangle3</code> is the most succinct of the three.  <code class="notranslate">RightTriangle1</code> is 12 lines long (besides being "wrong"), <code class="notranslate">RightTriangle2</code> is 13, <code class="notranslate">RightTriangle3</code> is just 10.  Additional observable or computed properties in <code class="notranslate">RightTriangle1</code> and <code class="notranslate">RightTriangle2</code> add two lines of code each; with <code class="notranslate">RightTriangle3</code> only one line of code is added each.</li>
<li>The TypeScript code in <code class="notranslate">RightTriangle3</code> is still very close to the emitted JavaScript (and therefore unlikely to create future incompatibility issues).</li>
<li>The new syntax is also very similar to the existing TypeScript parameter property declaration shorthand.</li>
<li>The pattern demonstrated in <code class="notranslate">RightTriangle3</code> enables a simple cut+paste migration path to implement a constructor (the developer would just have to paste in "this." on each line).  With TypeScript 1.0, implementing a constructor is a lot more work.  For example if converting <code class="notranslate">RightTriangle1</code> to <code class="notranslate">RightTriangle2</code>, the developer must determine and explicitly type out each member declaration with its type before migrating the instantiation code.</li>
</ul>
<p dir="auto"><strong>Specifics:</strong><br>
Inside a class constructor function only, a visibility modifier (<code class="notranslate">public</code>, <code class="notranslate">private</code>, or <code class="notranslate">protected</code>) may modify a property on the instance variable <code class="notranslate">this</code>.  If so, the statement is considered a declaration of that property on the class and the type is inferred according to the normal TypeScript rules.  The following example class <code class="notranslate">A</code> is legal under this proposal:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class A {
    constructor(property3: boolean) {
        public this.property1;  //any
        private this.property2 : string;  //string
        protected this.property3 = property3;  //boolean
    }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">A</span> <span class="pl-kos">{</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">property3</span>: <span class="pl-smi">boolean</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">public</span> <span class="pl-s1">this</span><span class="pl-kos">.</span><span class="pl-c1">property1</span><span class="pl-kos">;</span>  <span class="pl-c">//any</span>
        <span class="pl-s1">private</span> <span class="pl-s1">this</span><span class="pl-kos">.</span><span class="pl-c1">property2</span> : string<span class="pl-kos">;</span>  <span class="pl-c">//string</span>
        <span class="pl-s1">protected</span> <span class="pl-s1">this</span><span class="pl-kos">.</span><span class="pl-c1">property3</span> <span class="pl-c1">=</span> <span class="pl-s1">property3</span><span class="pl-kos">;</span>  <span class="pl-c">//boolean</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The above code is identical to this TypeScript 1.1 code:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class A {
    public property1;
    private property2: string;
    constructor(protected property3: boolean) {
    }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">A</span> <span class="pl-kos">{</span>
    <span class="pl-k">public</span> <span class="pl-c1">property1</span><span class="pl-kos">;</span>
    <span class="pl-k">private</span> <span class="pl-c1">property2</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-k">protected</span> <span class="pl-s1">property3</span>: <span class="pl-smi">boolean</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Use of a visibility modifier is otherwise not permitted within the body of a constructor.  For example, class <code class="notranslate">B</code> below would be a syntax error because <code class="notranslate">property1</code> is not qualified as a property of <code class="notranslate">this</code>.  This condition should cause a new emit-preventing type error along the lines of <code class="notranslate">Visibility modifiers within a constructor may only modify properties of "this".</code></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class B {
    constructor(val: string) {
        public property1 = val;
    }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">B</span> <span class="pl-kos">{</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">val</span>: <span class="pl-smi">string</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">public</span> <span class="pl-s1">property1</span> <span class="pl-c1">=</span> <span class="pl-s1">val</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Use of a visibility modifier is similarly not permitted within a normal function member.  For example, class <code class="notranslate">C</code> below would be a syntax error, because in this proposal class properties can only be declared in this manner within the constructor.  This condition should cause a new emit-preventing type error along the lines of <code class="notranslate">Visibility modifier declarations are only legal within the parameter list and body of a class constructor.</code></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class C {
    doSomething() {
        public this.property1: string = &quot;test&quot;;
    }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">C</span> <span class="pl-kos">{</span>
    <span class="pl-en">doSomething</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">public</span> <span class="pl-s1">this</span><span class="pl-kos">.</span><span class="pl-c1">property1</span>: string <span class="pl-c1">=</span> <span class="pl-s">"test"</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Use of the <code class="notranslate">static</code> modifier is similarly not permitted within a normal function member or the constructor.  For example, class <code class="notranslate">D</code> below would be a syntax error because under this proposal, <code class="notranslate">static</code> class properties can only be declared using the existing TypeScript 1.0 syntax (within the body of the class).  This condition should cause a new emit-preventing type error along the lines of <code class="notranslate">Shorthand visibility declarations may not be used on static properties.</code></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class D {
    constructor(val: boolean) {
        public static property1: string = &quot;test&quot;;
    }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">D</span> <span class="pl-kos">{</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">val</span>: <span class="pl-smi">boolean</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">public</span> <span class="pl-s1">static</span> property1: <span class="pl-s1">string</span> <span class="pl-c1">=</span> <span class="pl-s">"test"</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><strong>What happens if a declaration occurs inside of a branch?</strong><br>
For the purpose of the TypeScript type system, any branching, looping, etc. inside the constructor should be ignored.  Furthermore, the JavaScript should be emitted exactly as if the public, private, or protected modifier were not present.  Under this proposal, TypeScript should consider class <code class="notranslate">E</code> below to be valid.  At compile time, TypeScript will consider class <code class="notranslate">E</code> to have a property called <code class="notranslate">description</code> of type <code class="notranslate">string</code> (even though at runtime the initialization code would never execute).</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class E {
    constructor() {
        if (1 === 0) {
            public this.description = &quot;&quot;;
        }
    }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">E</span> <span class="pl-kos">{</span>
    <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-c1">1</span> <span class="pl-c1">===</span> <span class="pl-c1">0</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
            <span class="pl-k">public</span> <span class="pl-c1">this</span><span class="pl-kos">.</span><span class="pl-c1">description</span> <span class="pl-c1">=</span> <span class="pl-s">""</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><strong>What happens if there is a duplicate declaration and the types match?</strong><br>
This should not prevent the emit.  The second and successive duplicates should raise <code class="notranslate">error TS2300: Duplicate identifier 'PROPERTY_NAME_HERE'.</code> just like how existing duplicate declarations work.</p>
<p dir="auto"><strong>What happens if there is a duplicate, but one is a subtype of the other, or even if the types do not match?</strong><br>
The same type resolution logic should be applied if the duplicates occurred as simple type declarations in the class body (outside the constructor).  The second and successive duplicates should raise <code class="notranslate">error TS2300: Duplicate identifier 'PROPERTY_NAME_HERE'.</code>.  This should not prevent the emit.  This may incidentally result in downstream <code class="notranslate">error TS2339: Property 'PROPERTY_NAME_HERE' does not exist on type 'THE_PROPERTY_TYPE'.</code> wherever sub-properties of the property are used (just like in TypeScript 1.0).</p>
<p dir="auto"><strong>In all other scenarios</strong> (such as with inheritance chains, subtypes, supertypes, assignability relationships, and generics), the same behavior as a class written like <code class="notranslate">RightTriangle2</code> in TypeScript 1.0 should be used when evaluating what should happen with a class written like <code class="notranslate">RightTriangle3</code> using the new shorthand syntax.</p>
<p dir="auto">I believe that this syntax fits in nicely with both the goals and non-goals of TypeScript and I hope that you'll consider it or something similar.  Thanks for reading this.</p>