<p dir="auto">Not sure if this is a bug or just a feature that has not been implemented (yet), but given the following:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface Foo {
    member1: number;
    member2: boolean;
}

function bar(foo: Foo, member: &quot;member1&quot; | &quot;member2&quot;) {
    return foo[member]; // return type is inferred as any, whereas it should be number | boolean
}"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-smi">Foo</span> <span class="pl-kos">{</span>
    <span class="pl-c1">member1</span>: <span class="pl-smi">number</span><span class="pl-kos">;</span>
    <span class="pl-c1">member2</span>: <span class="pl-smi">boolean</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">function</span> <span class="pl-en">bar</span><span class="pl-kos">(</span><span class="pl-s1">foo</span>: <span class="pl-smi">Foo</span><span class="pl-kos">,</span> <span class="pl-s1">member</span>: <span class="pl-s">"member1"</span> <span class="pl-c1">|</span> <span class="pl-s">"member2"</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">foo</span><span class="pl-kos">[</span><span class="pl-s1">member</span><span class="pl-kos">]</span><span class="pl-kos">;</span> <span class="pl-c">// return type is inferred as any, whereas it should be number | boolean</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">I would expect the return type of <code class="notranslate">Foo</code> to be <code class="notranslate">number | boolean</code> instead of <code class="notranslate">any</code>. I see the same issue with function overloads:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare function bar2(field: &quot;field1&quot;): string;
declare function bar2(field: &quot;field2&quot;): number;
declare function bar2(field: string): any;

var field: &quot;field1&quot; | &quot;field2&quot; = &quot;field1&quot;;
var result = bar2(field); // inferred type of result is any, whereas it should be string | number"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">bar2</span><span class="pl-kos">(</span><span class="pl-s1">field</span>: <span class="pl-s">"field1"</span><span class="pl-kos">)</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">bar2</span><span class="pl-kos">(</span><span class="pl-s1">field</span>: <span class="pl-s">"field2"</span><span class="pl-kos">)</span>: <span class="pl-smi">number</span><span class="pl-kos">;</span>
<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">bar2</span><span class="pl-kos">(</span><span class="pl-s1">field</span>: <span class="pl-smi">string</span><span class="pl-kos">)</span>: <span class="pl-smi">any</span><span class="pl-kos">;</span>

<span class="pl-k">var</span> <span class="pl-s1">field</span>: <span class="pl-s">"field1"</span> <span class="pl-c1">|</span> <span class="pl-s">"field2"</span> <span class="pl-c1">=</span> <span class="pl-s">"field1"</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-s1">result</span> <span class="pl-c1">=</span> <span class="pl-en">bar2</span><span class="pl-kos">(</span><span class="pl-s1">field</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// inferred type of result is any, whereas it should be string | number</span></pre></div>
<p dir="auto">Note that his behavior is not limited to string literals; it also happens when overloading on type:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare function bar3(field: Date): string;
declare function bar3(field: number): number;
declare function bar3(field: any): any;

var field2: Date | number = 6;
var result2 = bar3(field2); // inferred type of result2 is any, whereas it should be string | number"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">bar3</span><span class="pl-kos">(</span><span class="pl-s1">field</span>: <span class="pl-smi">Date</span><span class="pl-kos">)</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">bar3</span><span class="pl-kos">(</span><span class="pl-s1">field</span>: <span class="pl-smi">number</span><span class="pl-kos">)</span>: <span class="pl-smi">number</span><span class="pl-kos">;</span>
<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">bar3</span><span class="pl-kos">(</span><span class="pl-s1">field</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span>: <span class="pl-smi">any</span><span class="pl-kos">;</span>

<span class="pl-k">var</span> <span class="pl-s1">field2</span>: <span class="pl-smi">Date</span> <span class="pl-c1">|</span> <span class="pl-smi">number</span> <span class="pl-c1">=</span> <span class="pl-c1">6</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-s1">result2</span> <span class="pl-c1">=</span> <span class="pl-en">bar3</span><span class="pl-kos">(</span><span class="pl-s1">field2</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// inferred type of result2 is any, whereas it should be string | number</span></pre></div>
<p dir="auto">This is with typescript 1.8.2</p>
<p dir="auto"><em>(This seems to have some things in common with <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="121849248" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/6080" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/6080/hovercard" href="https://github.com/microsoft/TypeScript/issues/6080">#6080</a> and is strongly related to <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="50384290" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/1295" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/1295/hovercard" href="https://github.com/microsoft/TypeScript/issues/1295">#1295</a> as <a href="https://github.com/Microsoft/TypeScript/issues/1295#issuecomment-202388214" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/1295/hovercard">it can be used to provide an alternative solution to it</a> but l opened this separately since I did not feel it was appropriate to continue discussing it there and wanted to approach it in a more generalized way)</em></p>
<p dir="auto">This would provide improved type safety for cases where an interface property is referenced through a string having a value that's known at compile time:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="type MyType = { &quot;ABC&quot;: number };
let x: MyType = { ABC: 42 };

const propName = &quot;ABC&quot;; // 'propName' received the literal type &quot;ABC&quot; (not string)
let y = x[propName]; // 'y' received the type MyType[&quot;ABC&quot;] which resolved to 'number'"><pre class="notranslate"><span class="pl-k">type</span> <span class="pl-smi">MyType</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span> <span class="pl-s">"ABC"</span>: <span class="pl-smi">number</span> <span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-k">let</span> <span class="pl-s1">x</span>: <span class="pl-smi">MyType</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span> <span class="pl-c1">ABC</span>: <span class="pl-c1">42</span> <span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">propName</span> <span class="pl-c1">=</span> <span class="pl-s">"ABC"</span><span class="pl-kos">;</span> <span class="pl-c">// 'propName' received the literal type "ABC" (not string)</span>
<span class="pl-k">let</span> <span class="pl-s1">y</span> <span class="pl-c1">=</span> <span class="pl-s1">x</span><span class="pl-kos">[</span><span class="pl-s1">propName</span><span class="pl-kos">]</span><span class="pl-kos">;</span> <span class="pl-c">// 'y' received the type MyType["ABC"] which resolved to 'number'</span></pre></div>
<p dir="auto">And with support for generic types added, this could work similarly, but resolve to an intermediate type of the form <code class="notranslate">T[S]</code> where <code class="notranslate">T</code> is an object type and <code class="notranslate">S</code> is a string literal type:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function func&lt;T extends object&gt;() {
    let x: T;
    const propName = &quot;ABC&quot;; // 'propName' received the literal type &quot;ABC&quot;
    let y = x[propName]; // 'y' would receive the type T[&quot;ABC&quot;]
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">func</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span> <span class="pl-k">extends</span> <span class="pl-smi">object</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> <span class="pl-s1">x</span>: <span class="pl-smi">T</span><span class="pl-kos">;</span>
    <span class="pl-k">const</span> <span class="pl-s1">propName</span> <span class="pl-c1">=</span> <span class="pl-s">"ABC"</span><span class="pl-kos">;</span> <span class="pl-c">// 'propName' received the literal type "ABC"</span>
    <span class="pl-k">let</span> <span class="pl-s1">y</span> <span class="pl-c1">=</span> <span class="pl-s1">x</span><span class="pl-kos">[</span><span class="pl-s1">propName</span><span class="pl-kos">]</span><span class="pl-kos">;</span> <span class="pl-c">// 'y' would receive the type T["ABC"]</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">This could combine with <code class="notranslate">readonly</code> function parameters to provide an alternative solution for <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="50384290" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/1295" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/1295/hovercard" href="https://github.com/microsoft/TypeScript/issues/1295">#1295</a> (which was actually <a href="https://github.com/Microsoft/TypeScript/issues/1295#issuecomment-202388214" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/1295/hovercard">where the idea was initially proposed</a>):</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function getProperty&lt;T extends object, S extends string&gt;(obj: T, readonly propName: S): T[S] {
    return obj[propName];
}

// Here T resolves to { ABC: number }, S resolves to the literal type &quot;ABC&quot;, 
// and T[S] resolves to number
let x = getProperty({ABC: 42}, &quot;ABC&quot;); // Type of 'x' is number

// Here T resolves to { ABC: number }, S resolves to the literal type &quot;CBA&quot; 
// and T[S] resolves to any
let x = getProperty({ABC: 42}, &quot;CBA&quot;); // Type of 'x' is any

// Here T resolves to { ABC: number }, S resolves to string
// and T[S] resolves to any
let x = getProperty({ABC: 42}, getRandomString()); // Type of 'x' is any"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">getProperty</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span> <span class="pl-k">extends</span> <span class="pl-smi">object</span><span class="pl-kos">,</span> <span class="pl-smi">S</span> <span class="pl-k">extends</span> <span class="pl-smi">string</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">obj</span>: <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-k">readonly</span> <span class="pl-s1">propName</span>: <span class="pl-smi">S</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span><span class="pl-kos">[</span><span class="pl-smi">S</span><span class="pl-kos">]</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">obj</span><span class="pl-kos">[</span><span class="pl-s1">propName</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-c">// Here T resolves to { ABC: number }, S resolves to the literal type "ABC", </span>
<span class="pl-c">// and T[S] resolves to number</span>
<span class="pl-k">let</span> <span class="pl-s1">x</span> <span class="pl-c1">=</span> <span class="pl-en">getProperty</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-c1">ABC</span>: <span class="pl-c1">42</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s">"ABC"</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// Type of 'x' is number</span>

<span class="pl-c">// Here T resolves to { ABC: number }, S resolves to the literal type "CBA" </span>
<span class="pl-c">// and T[S] resolves to any</span>
<span class="pl-k">let</span> <span class="pl-s1">x</span> <span class="pl-c1">=</span> <span class="pl-en">getProperty</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-c1">ABC</span>: <span class="pl-c1">42</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-s">"CBA"</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// Type of 'x' is any</span>

<span class="pl-c">// Here T resolves to { ABC: number }, S resolves to string</span>
<span class="pl-c">// and T[S] resolves to any</span>
<span class="pl-k">let</span> <span class="pl-s1">x</span> <span class="pl-c1">=</span> <span class="pl-en">getProperty</span><span class="pl-kos">(</span><span class="pl-kos">{</span><span class="pl-c1">ABC</span>: <span class="pl-c1">42</span><span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-en">getRandomString</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">// Type of 'x' is any</span></pre></div>
<p dir="auto">This may similarly extend to <a href="https://github.com/Microsoft/TypeScript/pull/7480" data-hovercard-type="pull_request" data-hovercard-url="/microsoft/TypeScript/pull/7480/hovercard">numeric literal types</a>, for tuples:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="type MyTupleType = [number, string, boolean];
let x: MyTupleType;
const index = 1; // 'index' received the literal type 1;

let y = x[index]; // 'y' received the type MyTupleType[1] which resolved to 'string'"><pre class="notranslate"><span class="pl-k">type</span> <span class="pl-smi">MyTupleType</span> <span class="pl-c1">=</span> <span class="pl-kos">[</span><span class="pl-smi">number</span><span class="pl-kos">,</span> <span class="pl-smi">string</span><span class="pl-kos">,</span> <span class="pl-smi">boolean</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
<span class="pl-k">let</span> <span class="pl-s1">x</span>: <span class="pl-smi">MyTupleType</span><span class="pl-kos">;</span>
<span class="pl-k">const</span> <span class="pl-s1">index</span> <span class="pl-c1">=</span> <span class="pl-c1">1</span><span class="pl-kos">;</span> <span class="pl-c">// 'index' received the literal type 1;</span>

<span class="pl-k">let</span> <span class="pl-s1">y</span> <span class="pl-c1">=</span> <span class="pl-s1">x</span><span class="pl-kos">[</span><span class="pl-s1">index</span><span class="pl-kos">]</span><span class="pl-kos">;</span> <span class="pl-c">// 'y' received the type MyTupleType[1] which resolved to 'string'</span></pre></div>
<p dir="auto">And work with generic tuples as well:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function getTupleElement&lt;T extends Array&lt;any&gt;, N extends number&gt;(tuple: T, readonly index: N): T[N] {
    return tuple[index];
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">getTupleElement</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span> <span class="pl-k">extends</span> <span class="pl-smi">Array</span><span class="pl-kos">&lt;</span><span class="pl-smi">any</span><span class="pl-kos">&gt;</span><span class="pl-kos">,</span> <span class="pl-smi">N</span> <span class="pl-k">extends</span> <span class="pl-smi">number</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">tuple</span>: <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-k">readonly</span> <span class="pl-s1">index</span>: <span class="pl-smi">N</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span><span class="pl-kos">[</span><span class="pl-smi">N</span><span class="pl-kos">]</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">tuple</span><span class="pl-kos">[</span><span class="pl-s1">index</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Same can be done with symbol literal types (haven't thought about that much though):</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function getSymbolProperty&lt;T extends object, S extends symbol&gt;(obj: T, readonly sym: S): T[S] {
    return obj[sym];
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">getSymbolProperty</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span> <span class="pl-k">extends</span> <span class="pl-smi">object</span><span class="pl-kos">,</span> <span class="pl-smi">S</span> <span class="pl-k">extends</span> <span class="pl-smi">symbol</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">obj</span>: <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-k">readonly</span> <span class="pl-s1">sym</span>: <span class="pl-smi">S</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span><span class="pl-kos">[</span><span class="pl-smi">S</span><span class="pl-kos">]</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">obj</span><span class="pl-kos">[</span><span class="pl-s1">sym</span><span class="pl-kos">]</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>