//// [keyofAndIndexedAccess.ts]

class Shape {
    name: string;
    width: number;
    height: number;
    visible: boolean;
}

class TaggedShape extends Shape {
    tag: string;
}

class Item {
    name: string;
    price: number;
}

class Options {
    visible: "yes" | "no";
}

type Dictionary<T> = { [x: string]: T };
type NumericallyIndexed<T> = { [x: number]: T };

const enum E { A, B, C }

type K00 = keyof any;  // string
type K01 = keyof string;  // "toString" | "charAt" | ...
type K02 = keyof number;  // "toString" | "toFixed" | "toExponential" | ...
type K03 = keyof boolean;  // "valueOf"
type K04 = keyof void;  // never
type K05 = keyof undefined;  // never
type K06 = keyof null;  // never
type K07 = keyof never;  // never

type K10 = keyof Shape;  // "name" | "width" | "height" | "visible"
type K11 = keyof Shape[];  // "length" | "toString" | ...
type K12 = keyof Dictionary<Shape>;  // string
type K13 = keyof {};  // never
type K14 = keyof Object;  // "constructor" | "toString" | ...
type K15 = keyof E;  // "toString" | "toFixed" | "toExponential" | ...
type K16 = keyof [string, number];  // "0" | "1" | "length" | "toString" | ...
type K17 = keyof (Shape | Item);  // "name"
type K18 = keyof (Shape & Item);  // "name" | "width" | "height" | "visible" | "price"
type K19 = keyof NumericallyIndexed<Shape> // never

type KeyOf<T> = keyof T;

type K20 = KeyOf<Shape>;  // "name" | "width" | "height" | "visible"
type K21 = KeyOf<Dictionary<Shape>>;  // string

type NAME = "name";
type WIDTH_OR_HEIGHT = "width" | "height";

type Q10 = Shape["name"];  // string
type Q11 = Shape["width" | "height"];  // number
type Q12 = Shape["name" | "visible"];  // string | boolean

type Q20 = Shape[NAME];  // string
type Q21 = Shape[WIDTH_OR_HEIGHT];  // number

type Q30 = [string, number][0];  // string
type Q31 = [string, number][1];  // number
type Q32 = [string, number][2];  // string | number
type Q33 = [string, number][E.A];  // string
type Q34 = [string, number][E.B];  // number
type Q35 = [string, number][E.C];  // string | number
type Q36 = [string, number]["0"];  // string
type Q37 = [string, number]["1"];  // string

type Q40 = (Shape | Options)["visible"];  // boolean | "yes" | "no"
type Q41 = (Shape & Options)["visible"];  // true & "yes" | true & "no" | false & "yes" | false & "no"

type Q50 = Dictionary<Shape>["howdy"];  // Shape
type Q51 = Dictionary<Shape>[123];  // Shape
type Q52 = Dictionary<Shape>[E.B];  // Shape

declare let cond: boolean;

function getProperty<T, K extends keyof T>(obj: T, key: K) {
    return obj[key];
}

function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) {
    obj[key] = value;
}

function f10(shape: Shape) {
    let name = getProperty(shape, "name");  // string
    let widthOrHeight = getProperty(shape, cond ? "width" : "height");  // number
    let nameOrVisible = getProperty(shape, cond ? "name" : "visible");  // string | boolean
    setProperty(shape, "name", "rectangle");
    setProperty(shape, cond ? "width" : "height", 10);
    setProperty(shape, cond ? "name" : "visible", true);  // Technically not safe
}

function f11(a: Shape[]) {
    let len = getProperty(a, "length");  // number
    setProperty(a, "length", len);
}

function f12(t: [Shape, boolean]) {
    let len = getProperty(t, "length");
    let s2 = getProperty(t, "0");  // Shape
    let b2 = getProperty(t, "1");  // boolean
}

function f13(foo: any, bar: any) {
    let x = getProperty(foo, "x");  // any
    let y = getProperty(foo, "100");  // any
    let z = getProperty(foo, bar);  // any
}

class Component<PropType> {
    props: PropType;
    getProperty<K extends keyof PropType>(key: K) {
        return this.props[key];
    }
    setProperty<K extends keyof PropType>(key: K, value: PropType[K]) {
        this.props[key] = value;
    }
}

function f20(component: Component<Shape>) {
    let name = component.getProperty("name");  // string
    let widthOrHeight = component.getProperty(cond ? "width" : "height");  // number
    let nameOrVisible = component.getProperty(cond ? "name" : "visible");  // string | boolean
    component.setProperty("name", "rectangle");
    component.setProperty(cond ? "width" : "height", 10)
    component.setProperty(cond ? "name" : "visible", true);  // Technically not safe
}

function pluck<T, K extends keyof T>(array: T[], key: K) {
    return array.map(x => x[key]);
}

function f30(shapes: Shape[]) {
    let names = pluck(shapes, "name");    // string[]
    let widths = pluck(shapes, "width");  // number[]
    let nameOrVisibles = pluck(shapes, cond ? "name" : "visible");  // (string | boolean)[]
}

function f31<K extends keyof Shape>(key: K) {
    const shape: Shape = { name: "foo", width: 5, height: 10, visible: true };
    return shape[key];  // Shape[K]
}

function f32<K extends "width" | "height">(key: K) {
    const shape: Shape = { name: "foo", width: 5, height: 10, visible: true };
    return shape[key];  // Shape[K]
}

function f33<S extends Shape, K extends keyof S>(shape: S, key: K) {
    let name = getProperty(shape, "name");
    let prop = getProperty(shape, key);
    return prop;
}

function f34(ts: TaggedShape) {
    let tag1 = f33(ts, "tag");
    let tag2 = getProperty(ts, "tag");
}

class C {
    public x: string;
    protected y: string;
    private z: string;
}

// Indexed access expressions have always permitted access to private and protected members.
// For consistency we also permit such access in indexed access types.
function f40(c: C) {
    type X = C["x"];
    type Y = C["y"];
    type Z = C["z"];
    let x: X = c["x"];
    let y: Y = c["y"];
    let z: Z = c["z"];
}

function f50<T>(k: keyof T, s: string) {
    const x1 = s as keyof T;
    const x2 = k as string;
}

function f51<T, K extends keyof T>(k: K, s: string) {
    const x1 = s as keyof T;
    const x2 = k as string;
}

function f52<T>(obj: { [x: string]: boolean }, k: keyof T, s: string, n: number) {
    const x1 = obj[s];
    const x2 = obj[n];
    const x3 = obj[k];
}

function f53<T, K extends keyof T>(obj: { [x: string]: boolean }, k: K, s: string, n: number) {
    const x1 = obj[s];
    const x2 = obj[n];
    const x3 = obj[k];
}

function f54<T>(obj: T, key: keyof T) {
    for (let s in obj[key]) {
    }
    const b = "foo" in obj[key];
}

function f55<T, K extends keyof T>(obj: T, key: K) {
    for (let s in obj[key]) {
    }
    const b = "foo" in obj[key];
}

function f60<T>(source: T, target: T) {
    for (let k in source) {
        target[k] = source[k];
    }
}

function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void) {
    func<{ a: any, b: any }, { a: any, c: any }>('a', 'a');
    func<{ a: any, b: any }, { a: any, c: any }>('a', 'b');
    func<{ a: any, b: any }, { a: any, c: any }>('a', 'c');
}

function f71(func: <T, U>(x: T, y: U) => Partial<T & U>) {
    let x = func({ a: 1, b: "hello" }, { c: true });
    x.a;  // number | undefined
    x.b;  // string | undefined
    x.c;  // boolean | undefined
}

function f72(func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]) {
    let a = func({ a: 1, b: "hello" }, { c: true }, 'a');  // number
    let b = func({ a: 1, b: "hello" }, { c: true }, 'b');  // string
    let c = func({ a: 1, b: "hello" }, { c: true }, 'c');  // boolean
}

function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]) {
    let a = func({ a: 1, b: "hello" }, { c: true }, 'a');  // number
    let b = func({ a: 1, b: "hello" }, { c: true }, 'b');  // string
    let c = func({ a: 1, b: "hello" }, { c: true }, 'c');  // boolean
}

function f74(func: <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]) {
    let a = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a');  // number
    let b = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b');  // string | boolean
}

function f80<T extends { a: { x: any } }>(obj: T) {
    let a1 = obj.a;  // { x: any }
    let a2 = obj['a'];  // { x: any }
    let a3 = obj['a'] as T['a'];  // T["a"]
    let x1 = obj.a.x;  // any
    let x2 = obj['a']['x'];  // any
    let x3 = obj['a']['x'] as T['a']['x'];  // T["a"]["x"]
}

function f81<T extends { a: { x: any } }>(obj: T) {
    return obj['a']['x'] as T['a']['x'];
}

function f82() {
    let x1 = f81({ a: { x: "hello" } });  // string
    let x2 = f81({ a: { x: 42 } });  // number
}

function f83<T extends { [x: string]: { x: any } }, K extends keyof T>(obj: T, key: K) {
    return obj[key]['x'] as T[K]['x'];
}

function f84() {
    let x1 = f83({ foo: { x: "hello" } }, "foo");  // string
    let x2 = f83({ bar: { x: 42 } }, "bar");  // number
}

class C1 {
    x: number;
    get<K extends keyof this>(key: K) {
        return this[key];
    }
    set<K extends keyof this>(key: K, value: this[K]) {
        this[key] = value;
    }
    foo() {
        let x1 = this.x;  // number
        let x2 = this["x"];  // number
        let x3 = this.get("x");  // this["x"]
        let x4 = getProperty(this, "x"); // this["x"]
        this.x = 42;
        this["x"] = 42;
        this.set("x", 42);
        setProperty(this, "x", 42);
    }
}

type S2 = {
    a: string;
    b: string;
};

function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K], x4: T[K]) {
    x1 = x2;
    x1 = x3;
    x1 = x4;
    x2 = x1;
    x2 = x3;
    x2 = x4;
    x3 = x1;
    x3 = x2;
    x3 = x4;
    x4 = x1;
    x4 = x2;
    x4 = x3;
    x1.length;
    x2.length;
    x3.length;
    x4.length;
}

// Repros from #12011

class Base {
    get<K extends keyof this>(prop: K) {
        return this[prop];
    }
    set<K extends keyof this>(prop: K, value: this[K]) {
        this[prop] = value;
    }
}

class Person extends Base {
    parts: number;
    constructor(parts: number) {
        super();
        this.set("parts", parts);
    }
    getParts() {
        return this.get("parts")
    }
}

class OtherPerson {
    parts: number;
    constructor(parts: number) {
        setProperty(this, "parts", parts);
    }
    getParts() {
        return getProperty(this, "parts")
    }
}

// Modified repro from #12544

function path<T, K1 extends keyof T>(obj: T, key1: K1): T[K1];
function path<T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2];
function path<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
function path(obj: any, ...keys: (string | number)[]): any;
function path(obj: any, ...keys: (string | number)[]): any {
    let result = obj;
    for (let k of keys) {
        result = result[k];
    }
    return result;
}

type Thing = {
    a: { x: number, y: string },
    b: boolean
};


function f1(thing: Thing) {
    let x1 = path(thing, 'a');  // { x: number, y: string }
    let x2 = path(thing, 'a', 'y');  // string
    let x3 = path(thing, 'b');  // boolean
    let x4 = path(thing, ...['a', 'x']);  // any
}

// Repro from comment in #12114

const assignTo2 = <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) =>
    (value: T[K1][K2]) => object[key1][key2] = value;

// Modified repro from #12573

declare function one<T>(handler: (t: T) => void): T
var empty = one(() => {}) // inferred as {}, expected

type Handlers<T> = { [K in keyof T]: (t: T[K]) => void }
declare function on<T>(handlerHash: Handlers<T>): T
var hashOfEmpty1 = on({ test: () => {} });  // {}
var hashOfEmpty2 = on({ test: (x: boolean) => {} });  // { test: boolean }

// Repro from #12624

interface Options1<Data, Computed> {
    data?: Data
    computed?: Computed;
}

declare class Component1<Data, Computed> {
    constructor(options: Options1<Data, Computed>);
    get<K extends keyof (Data & Computed)>(key: K): (Data & Computed)[K];
}

let c1 = new Component1({
    data: {
        hello: ""
    }
});

c1.get("hello");

// Repro from #12625

interface Options2<Data, Computed> {
    data?: Data
    computed?: Computed;
}

declare class Component2<Data, Computed> {
    constructor(options: Options2<Data, Computed>);
    get<K extends keyof Data | keyof Computed>(key: K): (Data & Computed)[K];
}

// Repro from #12641

interface R {
    p: number;
}

function f<K extends keyof R>(p: K) {
    let a: any;
    a[p].add;  // any
}

// Repro from #12651

type MethodDescriptor = {
	name: string;
	args: any[];
	returnValue: any;
}

declare function dispatchMethod<M extends MethodDescriptor>(name: M['name'], args: M['args']): M['returnValue'];

type SomeMethodDescriptor = {
	name: "someMethod";
	args: [string, number];
	returnValue: string[];
}

let result = dispatchMethod<SomeMethodDescriptor>("someMethod", ["hello", 35]);

// Repro from #13073

type KeyTypes = "a" | "b"
let MyThingy: { [key in KeyTypes]: string[] };

function addToMyThingy<S extends KeyTypes>(key: S) {
    MyThingy[key].push("a");
}

// Repro from #13102

type Handler<T> = {
    onChange: (name: keyof T) => void;
};

function onChangeGenericFunction<T>(handler: Handler<T & {preset: number}>) {
    handler.onChange('preset')
}

// Repro from #13285

function updateIds<T extends Record<K, string>, K extends string>(
    obj: T,
    idFields: K[],
    idMapping: { [oldId: string]: string }
): Record<K, string> {
    for (const idField of idFields) {
        const newId = idMapping[obj[idField]];
        if (newId) {
            obj[idField] = newId;
        }
    }
    return obj;
}

// Repro from #13285

function updateIds2<T extends { [x: string]: string }, K extends keyof T>(
    obj: T,
    key: K,
    stringMap: { [oldId: string]: string }
) {
    var x = obj[key];
    stringMap[x]; // Should be OK.
}

// Repro from #13514

declare function head<T extends Array<any>>(list: T): T[0];

// Repro from #13604

class A<T> {
	props: T & { foo: string };
}

class B extends A<{ x: number}> {
	f(p: this["props"]) {
		p.x;
	}
}

// Repro from #13749

class Form<T> {
    private childFormFactories: {[K in keyof T]: (v: T[K]) => Form<T[K]>}

    public set<K extends keyof T>(prop: K, value: T[K]) {
        this.childFormFactories[prop](value)
    }
}

// Repro from #13787

class SampleClass<P> {
    public props: Readonly<P>;
    constructor(props: P) {
        this.props = Object.freeze(props);
    }
}

interface Foo {
    foo: string;
}

declare function merge<T, U>(obj1: T, obj2: U): T & U;

class AnotherSampleClass<T> extends SampleClass<T & Foo> {
    constructor(props: T) {
        const foo: Foo = { foo: "bar" };
        super(merge(props, foo));
    }

    public brokenMethod() {
        this.props.foo.concat;
    }
}
new AnotherSampleClass({});


//// [keyofAndIndexedAccess.js]
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var Shape = (function () {
    function Shape() {
    }
    return Shape;
}());
var TaggedShape = (function (_super) {
    __extends(TaggedShape, _super);
    function TaggedShape() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return TaggedShape;
}(Shape));
var Item = (function () {
    function Item() {
    }
    return Item;
}());
var Options = (function () {
    function Options() {
    }
    return Options;
}());
function getProperty(obj, key) {
    return obj[key];
}
function setProperty(obj, key, value) {
    obj[key] = value;
}
function f10(shape) {
    var name = getProperty(shape, "name"); // string
    var widthOrHeight = getProperty(shape, cond ? "width" : "height"); // number
    var nameOrVisible = getProperty(shape, cond ? "name" : "visible"); // string | boolean
    setProperty(shape, "name", "rectangle");
    setProperty(shape, cond ? "width" : "height", 10);
    setProperty(shape, cond ? "name" : "visible", true); // Technically not safe
}
function f11(a) {
    var len = getProperty(a, "length"); // number
    setProperty(a, "length", len);
}
function f12(t) {
    var len = getProperty(t, "length");
    var s2 = getProperty(t, "0"); // Shape
    var b2 = getProperty(t, "1"); // boolean
}
function f13(foo, bar) {
    var x = getProperty(foo, "x"); // any
    var y = getProperty(foo, "100"); // any
    var z = getProperty(foo, bar); // any
}
var Component = (function () {
    function Component() {
    }
    Component.prototype.getProperty = function (key) {
        return this.props[key];
    };
    Component.prototype.setProperty = function (key, value) {
        this.props[key] = value;
    };
    return Component;
}());
function f20(component) {
    var name = component.getProperty("name"); // string
    var widthOrHeight = component.getProperty(cond ? "width" : "height"); // number
    var nameOrVisible = component.getProperty(cond ? "name" : "visible"); // string | boolean
    component.setProperty("name", "rectangle");
    component.setProperty(cond ? "width" : "height", 10);
    component.setProperty(cond ? "name" : "visible", true); // Technically not safe
}
function pluck(array, key) {
    return array.map(function (x) { return x[key]; });
}
function f30(shapes) {
    var names = pluck(shapes, "name"); // string[]
    var widths = pluck(shapes, "width"); // number[]
    var nameOrVisibles = pluck(shapes, cond ? "name" : "visible"); // (string | boolean)[]
}
function f31(key) {
    var shape = { name: "foo", width: 5, height: 10, visible: true };
    return shape[key]; // Shape[K]
}
function f32(key) {
    var shape = { name: "foo", width: 5, height: 10, visible: true };
    return shape[key]; // Shape[K]
}
function f33(shape, key) {
    var name = getProperty(shape, "name");
    var prop = getProperty(shape, key);
    return prop;
}
function f34(ts) {
    var tag1 = f33(ts, "tag");
    var tag2 = getProperty(ts, "tag");
}
var C = (function () {
    function C() {
    }
    return C;
}());
// Indexed access expressions have always permitted access to private and protected members.
// For consistency we also permit such access in indexed access types.
function f40(c) {
    var x = c["x"];
    var y = c["y"];
    var z = c["z"];
}
function f50(k, s) {
    var x1 = s;
    var x2 = k;
}
function f51(k, s) {
    var x1 = s;
    var x2 = k;
}
function f52(obj, k, s, n) {
    var x1 = obj[s];
    var x2 = obj[n];
    var x3 = obj[k];
}
function f53(obj, k, s, n) {
    var x1 = obj[s];
    var x2 = obj[n];
    var x3 = obj[k];
}
function f54(obj, key) {
    for (var s in obj[key]) {
    }
    var b = "foo" in obj[key];
}
function f55(obj, key) {
    for (var s in obj[key]) {
    }
    var b = "foo" in obj[key];
}
function f60(source, target) {
    for (var k in source) {
        target[k] = source[k];
    }
}
function f70(func) {
    func('a', 'a');
    func('a', 'b');
    func('a', 'c');
}
function f71(func) {
    var x = func({ a: 1, b: "hello" }, { c: true });
    x.a; // number | undefined
    x.b; // string | undefined
    x.c; // boolean | undefined
}
function f72(func) {
    var a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
    var b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
    var c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
}
function f73(func) {
    var a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number
    var b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string
    var c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean
}
function f74(func) {
    var a = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a'); // number
    var b = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b'); // string | boolean
}
function f80(obj) {
    var a1 = obj.a; // { x: any }
    var a2 = obj['a']; // { x: any }
    var a3 = obj['a']; // T["a"]
    var x1 = obj.a.x; // any
    var x2 = obj['a']['x']; // any
    var x3 = obj['a']['x']; // T["a"]["x"]
}
function f81(obj) {
    return obj['a']['x'];
}
function f82() {
    var x1 = f81({ a: { x: "hello" } }); // string
    var x2 = f81({ a: { x: 42 } }); // number
}
function f83(obj, key) {
    return obj[key]['x'];
}
function f84() {
    var x1 = f83({ foo: { x: "hello" } }, "foo"); // string
    var x2 = f83({ bar: { x: 42 } }, "bar"); // number
}
var C1 = (function () {
    function C1() {
    }
    C1.prototype.get = function (key) {
        return this[key];
    };
    C1.prototype.set = function (key, value) {
        this[key] = value;
    };
    C1.prototype.foo = function () {
        var x1 = this.x; // number
        var x2 = this["x"]; // number
        var x3 = this.get("x"); // this["x"]
        var x4 = getProperty(this, "x"); // this["x"]
        this.x = 42;
        this["x"] = 42;
        this.set("x", 42);
        setProperty(this, "x", 42);
    };
    return C1;
}());
function f90(x1, x2, x3, x4) {
    x1 = x2;
    x1 = x3;
    x1 = x4;
    x2 = x1;
    x2 = x3;
    x2 = x4;
    x3 = x1;
    x3 = x2;
    x3 = x4;
    x4 = x1;
    x4 = x2;
    x4 = x3;
    x1.length;
    x2.length;
    x3.length;
    x4.length;
}
// Repros from #12011
var Base = (function () {
    function Base() {
    }
    Base.prototype.get = function (prop) {
        return this[prop];
    };
    Base.prototype.set = function (prop, value) {
        this[prop] = value;
    };
    return Base;
}());
var Person = (function (_super) {
    __extends(Person, _super);
    function Person(parts) {
        var _this = _super.call(this) || this;
        _this.set("parts", parts);
        return _this;
    }
    Person.prototype.getParts = function () {
        return this.get("parts");
    };
    return Person;
}(Base));
var OtherPerson = (function () {
    function OtherPerson(parts) {
        setProperty(this, "parts", parts);
    }
    OtherPerson.prototype.getParts = function () {
        return getProperty(this, "parts");
    };
    return OtherPerson;
}());
function path(obj) {
    var keys = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        keys[_i - 1] = arguments[_i];
    }
    var result = obj;
    for (var _a = 0, keys_1 = keys; _a < keys_1.length; _a++) {
        var k = keys_1[_a];
        result = result[k];
    }
    return result;
}
function f1(thing) {
    var x1 = path(thing, 'a'); // { x: number, y: string }
    var x2 = path(thing, 'a', 'y'); // string
    var x3 = path(thing, 'b'); // boolean
    var x4 = path.apply(void 0, [thing].concat(['a', 'x'])); // any
}
// Repro from comment in #12114
var assignTo2 = function (object, key1, key2) {
    return function (value) { return object[key1][key2] = value; };
};
var empty = one(function () { }); // inferred as {}, expected
var hashOfEmpty1 = on({ test: function () { } }); // {}
var hashOfEmpty2 = on({ test: function (x) { } }); // { test: boolean }
var c1 = new Component1({
    data: {
        hello: ""
    }
});
c1.get("hello");
function f(p) {
    var a;
    a[p].add; // any
}
var result = dispatchMethod("someMethod", ["hello", 35]);
var MyThingy;
function addToMyThingy(key) {
    MyThingy[key].push("a");
}
function onChangeGenericFunction(handler) {
    handler.onChange('preset');
}
// Repro from #13285
function updateIds(obj, idFields, idMapping) {
    for (var _i = 0, idFields_1 = idFields; _i < idFields_1.length; _i++) {
        var idField = idFields_1[_i];
        var newId = idMapping[obj[idField]];
        if (newId) {
            obj[idField] = newId;
        }
    }
    return obj;
}
// Repro from #13285
function updateIds2(obj, key, stringMap) {
    var x = obj[key];
    stringMap[x]; // Should be OK.
}
// Repro from #13604
var A = (function () {
    function A() {
    }
    return A;
}());
var B = (function (_super) {
    __extends(B, _super);
    function B() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    B.prototype.f = function (p) {
        p.x;
    };
    return B;
}(A));
// Repro from #13749
var Form = (function () {
    function Form() {
    }
    Form.prototype.set = function (prop, value) {
        this.childFormFactories[prop](value);
    };
    return Form;
}());
// Repro from #13787
var SampleClass = (function () {
    function SampleClass(props) {
        this.props = Object.freeze(props);
    }
    return SampleClass;
}());
var AnotherSampleClass = (function (_super) {
    __extends(AnotherSampleClass, _super);
    function AnotherSampleClass(props) {
        var _this = this;
        var foo = { foo: "bar" };
        _this = _super.call(this, merge(props, foo)) || this;
        return _this;
    }
    AnotherSampleClass.prototype.brokenMethod = function () {
        this.props.foo.concat;
    };
    return AnotherSampleClass;
}(SampleClass));
new AnotherSampleClass({});


//// [keyofAndIndexedAccess.d.ts]
declare class Shape {
    name: string;
    width: number;
    height: number;
    visible: boolean;
}
declare class TaggedShape extends Shape {
    tag: string;
}
declare class Item {
    name: string;
    price: number;
}
declare class Options {
    visible: "yes" | "no";
}
declare type Dictionary<T> = {
    [x: string]: T;
};
declare type NumericallyIndexed<T> = {
    [x: number]: T;
};
declare const enum E {
    A = 0,
    B = 1,
    C = 2,
}
declare type K00 = keyof any;
declare type K01 = keyof string;
declare type K02 = keyof number;
declare type K03 = keyof boolean;
declare type K04 = keyof void;
declare type K05 = keyof undefined;
declare type K06 = keyof null;
declare type K07 = keyof never;
declare type K10 = keyof Shape;
declare type K11 = keyof Shape[];
declare type K12 = keyof Dictionary<Shape>;
declare type K13 = keyof {};
declare type K14 = keyof Object;
declare type K15 = keyof E;
declare type K16 = keyof [string, number];
declare type K17 = keyof (Shape | Item);
declare type K18 = keyof (Shape & Item);
declare type K19 = keyof NumericallyIndexed<Shape>;
declare type KeyOf<T> = keyof T;
declare type K20 = KeyOf<Shape>;
declare type K21 = KeyOf<Dictionary<Shape>>;
declare type NAME = "name";
declare type WIDTH_OR_HEIGHT = "width" | "height";
declare type Q10 = Shape["name"];
declare type Q11 = Shape["width" | "height"];
declare type Q12 = Shape["name" | "visible"];
declare type Q20 = Shape[NAME];
declare type Q21 = Shape[WIDTH_OR_HEIGHT];
declare type Q30 = [string, number][0];
declare type Q31 = [string, number][1];
declare type Q32 = [string, number][2];
declare type Q33 = [string, number][E.A];
declare type Q34 = [string, number][E.B];
declare type Q35 = [string, number][E.C];
declare type Q36 = [string, number]["0"];
declare type Q37 = [string, number]["1"];
declare type Q40 = (Shape | Options)["visible"];
declare type Q41 = (Shape & Options)["visible"];
declare type Q50 = Dictionary<Shape>["howdy"];
declare type Q51 = Dictionary<Shape>[123];
declare type Q52 = Dictionary<Shape>[E.B];
declare let cond: boolean;
declare function getProperty<T, K extends keyof T>(obj: T, key: K): T[K];
declare function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]): void;
declare function f10(shape: Shape): void;
declare function f11(a: Shape[]): void;
declare function f12(t: [Shape, boolean]): void;
declare function f13(foo: any, bar: any): void;
declare class Component<PropType> {
    props: PropType;
    getProperty<K extends keyof PropType>(key: K): PropType[K];
    setProperty<K extends keyof PropType>(key: K, value: PropType[K]): void;
}
declare function f20(component: Component<Shape>): void;
declare function pluck<T, K extends keyof T>(array: T[], key: K): T[K][];
declare function f30(shapes: Shape[]): void;
declare function f31<K extends keyof Shape>(key: K): Shape[K];
declare function f32<K extends "width" | "height">(key: K): Shape[K];
declare function f33<S extends Shape, K extends keyof S>(shape: S, key: K): S[K];
declare function f34(ts: TaggedShape): void;
declare class C {
    x: string;
    protected y: string;
    private z;
}
declare function f40(c: C): void;
declare function f50<T>(k: keyof T, s: string): void;
declare function f51<T, K extends keyof T>(k: K, s: string): void;
declare function f52<T>(obj: {
    [x: string]: boolean;
}, k: keyof T, s: string, n: number): void;
declare function f53<T, K extends keyof T>(obj: {
    [x: string]: boolean;
}, k: K, s: string, n: number): void;
declare function f54<T>(obj: T, key: keyof T): void;
declare function f55<T, K extends keyof T>(obj: T, key: K): void;
declare function f60<T>(source: T, target: T): void;
declare function f70(func: <T, U>(k1: keyof (T | U), k2: keyof (T & U)) => void): void;
declare function f71(func: <T, U>(x: T, y: U) => Partial<T & U>): void;
declare function f72(func: <T, U, K extends keyof T | keyof U>(x: T, y: U, k: K) => (T & U)[K]): void;
declare function f73(func: <T, U, K extends keyof (T & U)>(x: T, y: U, k: K) => (T & U)[K]): void;
declare function f74(func: <T, U, K extends keyof (T | U)>(x: T, y: U, k: K) => (T | U)[K]): void;
declare function f80<T extends {
    a: {
        x: any;
    };
}>(obj: T): void;
declare function f81<T extends {
    a: {
        x: any;
    };
}>(obj: T): T["a"]["x"];
declare function f82(): void;
declare function f83<T extends {
    [x: string]: {
        x: any;
    };
}, K extends keyof T>(obj: T, key: K): T[K]["x"];
declare function f84(): void;
declare class C1 {
    x: number;
    get<K extends keyof this>(key: K): this[K];
    set<K extends keyof this>(key: K, value: this[K]): void;
    foo(): void;
}
declare type S2 = {
    a: string;
    b: string;
};
declare function f90<T extends S2, K extends keyof S2>(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K], x4: T[K]): void;
declare class Base {
    get<K extends keyof this>(prop: K): this[K];
    set<K extends keyof this>(prop: K, value: this[K]): void;
}
declare class Person extends Base {
    parts: number;
    constructor(parts: number);
    getParts(): this["parts"];
}
declare class OtherPerson {
    parts: number;
    constructor(parts: number);
    getParts(): this["parts"];
}
declare function path<T, K1 extends keyof T>(obj: T, key1: K1): T[K1];
declare function path<T, K1 extends keyof T, K2 extends keyof T[K1]>(obj: T, key1: K1, key2: K2): T[K1][K2];
declare function path<T, K1 extends keyof T, K2 extends keyof T[K1], K3 extends keyof T[K1][K2]>(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
declare function path(obj: any, ...keys: (string | number)[]): any;
declare type Thing = {
    a: {
        x: number;
        y: string;
    };
    b: boolean;
};
declare function f1(thing: Thing): void;
declare const assignTo2: <T, K1 extends keyof T, K2 extends keyof T[K1]>(object: T, key1: K1, key2: K2) => (value: T[K1][K2]) => T[K1][K2];
declare function one<T>(handler: (t: T) => void): T;
declare var empty: {};
declare type Handlers<T> = {
    [K in keyof T]: (t: T[K]) => void;
};
declare function on<T>(handlerHash: Handlers<T>): T;
declare var hashOfEmpty1: {};
declare var hashOfEmpty2: {
    test: boolean;
};
interface Options1<Data, Computed> {
    data?: Data;
    computed?: Computed;
}
declare class Component1<Data, Computed> {
    constructor(options: Options1<Data, Computed>);
    get<K extends keyof (Data & Computed)>(key: K): (Data & Computed)[K];
}
declare let c1: Component1<{
    hello: string;
}, {}>;
interface Options2<Data, Computed> {
    data?: Data;
    computed?: Computed;
}
declare class Component2<Data, Computed> {
    constructor(options: Options2<Data, Computed>);
    get<K extends keyof Data | keyof Computed>(key: K): (Data & Computed)[K];
}
interface R {
    p: number;
}
declare function f<K extends keyof R>(p: K): void;
declare type MethodDescriptor = {
    name: string;
    args: any[];
    returnValue: any;
};
declare function dispatchMethod<M extends MethodDescriptor>(name: M['name'], args: M['args']): M['returnValue'];
declare type SomeMethodDescriptor = {
    name: "someMethod";
    args: [string, number];
    returnValue: string[];
};
declare let result: string[];
declare type KeyTypes = "a" | "b";
declare let MyThingy: {
    [key in KeyTypes]: string[];
};
declare function addToMyThingy<S extends KeyTypes>(key: S): void;
declare type Handler<T> = {
    onChange: (name: keyof T) => void;
};
declare function onChangeGenericFunction<T>(handler: Handler<T & {
    preset: number;
}>): void;
declare function updateIds<T extends Record<K, string>, K extends string>(obj: T, idFields: K[], idMapping: {
    [oldId: string]: string;
}): Record<K, string>;
declare function updateIds2<T extends {
    [x: string]: string;
}, K extends keyof T>(obj: T, key: K, stringMap: {
    [oldId: string]: string;
}): void;
declare function head<T extends Array<any>>(list: T): T[0];
declare class A<T> {
    props: T & {
        foo: string;
    };
}
declare class B extends A<{
    x: number;
}> {
    f(p: this["props"]): void;
}
declare class Form<T> {
    private childFormFactories;
    set<K extends keyof T>(prop: K, value: T[K]): void;
}
declare class SampleClass<P> {
    props: Readonly<P>;
    constructor(props: P);
}
interface Foo {
    foo: string;
}
declare function merge<T, U>(obj1: T, obj2: U): T & U;
declare class AnotherSampleClass<T> extends SampleClass<T & Foo> {
    constructor(props: T);
    brokenMethod(): void;
}
