diff --git a/tests/baselines/reference/keyofAndIndexedAccess.js b/tests/baselines/reference/keyofAndIndexedAccess.js new file mode 100644 index 00000000000..5d986f3e892 --- /dev/null +++ b/tests/baselines/reference/keyofAndIndexedAccess.js @@ -0,0 +1,350 @@ +//// [keyofAndIndexedAccess.ts] + +class Shape { + name: string; + width: number; + height: number; + visible: boolean; +} + +class Item { + name: string; + price: number; +} + +class Options { + visible: "yes" | "no"; +} + +type Dictionary = { [x: string]: T }; + +const enum E { A, B, C } + +type K00 = keyof any; // string | number +type K01 = keyof string; // number | "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[]; // number | "length" | "toString" | ... +type K12 = keyof Dictionary; // string | number +type K13 = keyof {}; // never +type K14 = keyof Object; // "constructor" | "toString" | ... +type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ... +type K16 = keyof [string, number]; // number | "0" | "1" | "length" | "toString" | ... +type K17 = keyof (Shape | Item); // "name" +type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "price" + +type KeyOf = keyof T; + +type K20 = KeyOf; // "name" | "width" | "height" | "visible" +type K21 = KeyOf>; // string | number + +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["howdy"]; // Shape +type Q51 = Dictionary[123]; // Shape +type Q52 = Dictionary[E.B]; // Shape + +declare let cond: boolean; + +function getProperty(obj: T, key: K) { + return obj[key]; +} + +function setProperty(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 + let shape = getProperty(a, 1000); // Shape + setProperty(a, 1000, getProperty(a, 1001)); +} + +function f12(t: [Shape, boolean]) { + let len = getProperty(t, "length"); + let s1 = getProperty(t, 0); // Shape + let s2 = getProperty(t, "0"); // Shape + let b1 = getProperty(t, 1); // boolean + let b2 = getProperty(t, "1"); // boolean + let x1 = getProperty(t, 2); // Shape | 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 { + props: PropType; + getProperty(key: K) { + return this.props[key]; + } + setProperty(key: K, value: PropType[K]) { + this.props[key] = value; + } +} + +function f20(component: Component) { + 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(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(key: K) { + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; + return shape[key]; // Shape[K] +} + +function f32(key: K) { + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; + return shape[key]; // Shape[K] +} + +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"]; +} + +//// [keyofAndIndexedAccess.js] +var Shape = (function () { + function Shape() { + } + return 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 + var shape = getProperty(a, 1000); // Shape + setProperty(a, 1000, getProperty(a, 1001)); +} +function f12(t) { + var len = getProperty(t, "length"); + var s1 = getProperty(t, 0); // Shape + var s2 = getProperty(t, "0"); // Shape + var b1 = getProperty(t, 1); // boolean + var b2 = getProperty(t, "1"); // boolean + var x1 = getProperty(t, 2); // Shape | 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] +} +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"]; +} + + +//// [keyofAndIndexedAccess.d.ts] +declare class Shape { + name: string; + width: number; + height: number; + visible: boolean; +} +declare class Item { + name: string; + price: number; +} +declare class Options { + visible: "yes" | "no"; +} +declare type Dictionary = { + [x: string]: 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; +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 KeyOf = keyof T; +declare type K20 = KeyOf; +declare type K21 = KeyOf>; +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["howdy"]; +declare type Q51 = Dictionary[123]; +declare type Q52 = Dictionary[E.B]; +declare let cond: boolean; +declare function getProperty(obj: T, key: K): T[K]; +declare function setProperty(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 { + props: PropType; + getProperty(key: K): PropType[K]; + setProperty(key: K, value: PropType[K]): void; +} +declare function f20(component: Component): void; +declare function pluck(array: T[], key: K): T[K][]; +declare function f30(shapes: Shape[]): void; +declare function f31(key: K): Shape[K]; +declare function f32(key: K): Shape[K]; +declare class C { + x: string; + protected y: string; + private z; +} +declare function f40(c: C): void; diff --git a/tests/baselines/reference/keyofAndIndexedAccess.symbols b/tests/baselines/reference/keyofAndIndexedAccess.symbols new file mode 100644 index 00000000000..d3e967ed125 --- /dev/null +++ b/tests/baselines/reference/keyofAndIndexedAccess.symbols @@ -0,0 +1,577 @@ +=== tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts === + +class Shape { +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + + name: string; +>name : Symbol(Shape.name, Decl(keyofAndIndexedAccess.ts, 1, 13)) + + width: number; +>width : Symbol(Shape.width, Decl(keyofAndIndexedAccess.ts, 2, 17)) + + height: number; +>height : Symbol(Shape.height, Decl(keyofAndIndexedAccess.ts, 3, 18)) + + visible: boolean; +>visible : Symbol(Shape.visible, Decl(keyofAndIndexedAccess.ts, 4, 19)) +} + +class Item { +>Item : Symbol(Item, Decl(keyofAndIndexedAccess.ts, 6, 1)) + + name: string; +>name : Symbol(Item.name, Decl(keyofAndIndexedAccess.ts, 8, 12)) + + price: number; +>price : Symbol(Item.price, Decl(keyofAndIndexedAccess.ts, 9, 17)) +} + +class Options { +>Options : Symbol(Options, Decl(keyofAndIndexedAccess.ts, 11, 1)) + + visible: "yes" | "no"; +>visible : Symbol(Options.visible, Decl(keyofAndIndexedAccess.ts, 13, 15)) +} + +type Dictionary = { [x: string]: T }; +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 17, 16)) +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 17, 24)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 17, 16)) + +const enum E { A, B, C } +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) +>A : Symbol(E.A, Decl(keyofAndIndexedAccess.ts, 19, 14)) +>B : Symbol(E.B, Decl(keyofAndIndexedAccess.ts, 19, 17)) +>C : Symbol(E.C, Decl(keyofAndIndexedAccess.ts, 19, 20)) + +type K00 = keyof any; // string | number +>K00 : Symbol(K00, Decl(keyofAndIndexedAccess.ts, 19, 24)) + +type K01 = keyof string; // number | "toString" | "charAt" | ... +>K01 : Symbol(K01, Decl(keyofAndIndexedAccess.ts, 21, 21)) + +type K02 = keyof number; // "toString" | "toFixed" | "toExponential" | ... +>K02 : Symbol(K02, Decl(keyofAndIndexedAccess.ts, 22, 24)) + +type K03 = keyof boolean; // "valueOf" +>K03 : Symbol(K03, Decl(keyofAndIndexedAccess.ts, 23, 24)) + +type K04 = keyof void; // never +>K04 : Symbol(K04, Decl(keyofAndIndexedAccess.ts, 24, 25)) + +type K05 = keyof undefined; // never +>K05 : Symbol(K05, Decl(keyofAndIndexedAccess.ts, 25, 22)) + +type K06 = keyof null; // never +>K06 : Symbol(K06, Decl(keyofAndIndexedAccess.ts, 26, 27)) + +type K07 = keyof never; // never +>K07 : Symbol(K07, Decl(keyofAndIndexedAccess.ts, 27, 22)) + +type K10 = keyof Shape; // "name" | "width" | "height" | "visible" +>K10 : Symbol(K10, Decl(keyofAndIndexedAccess.ts, 28, 23)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + +type K11 = keyof Shape[]; // number | "length" | "toString" | ... +>K11 : Symbol(K11, Decl(keyofAndIndexedAccess.ts, 30, 23)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + +type K12 = keyof Dictionary; // string | number +>K12 : Symbol(K12, Decl(keyofAndIndexedAccess.ts, 31, 25)) +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + +type K13 = keyof {}; // never +>K13 : Symbol(K13, Decl(keyofAndIndexedAccess.ts, 32, 35)) + +type K14 = keyof Object; // "constructor" | "toString" | ... +>K14 : Symbol(K14, Decl(keyofAndIndexedAccess.ts, 33, 20)) +>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ... +>K15 : Symbol(K15, Decl(keyofAndIndexedAccess.ts, 34, 24)) +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) + +type K16 = keyof [string, number]; // number | "0" | "1" | "length" | "toString" | ... +>K16 : Symbol(K16, Decl(keyofAndIndexedAccess.ts, 35, 19)) + +type K17 = keyof (Shape | Item); // "name" +>K17 : Symbol(K17, Decl(keyofAndIndexedAccess.ts, 36, 34)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) +>Item : Symbol(Item, Decl(keyofAndIndexedAccess.ts, 6, 1)) + +type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "price" +>K18 : Symbol(K18, Decl(keyofAndIndexedAccess.ts, 37, 32)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) +>Item : Symbol(Item, Decl(keyofAndIndexedAccess.ts, 6, 1)) + +type KeyOf = keyof T; +>KeyOf : Symbol(KeyOf, Decl(keyofAndIndexedAccess.ts, 38, 32)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 40, 11)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 40, 11)) + +type K20 = KeyOf; // "name" | "width" | "height" | "visible" +>K20 : Symbol(K20, Decl(keyofAndIndexedAccess.ts, 40, 24)) +>KeyOf : Symbol(KeyOf, Decl(keyofAndIndexedAccess.ts, 38, 32)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + +type K21 = KeyOf>; // string | number +>K21 : Symbol(K21, Decl(keyofAndIndexedAccess.ts, 42, 24)) +>KeyOf : Symbol(KeyOf, Decl(keyofAndIndexedAccess.ts, 38, 32)) +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + +type NAME = "name"; +>NAME : Symbol(NAME, Decl(keyofAndIndexedAccess.ts, 43, 36)) + +type WIDTH_OR_HEIGHT = "width" | "height"; +>WIDTH_OR_HEIGHT : Symbol(WIDTH_OR_HEIGHT, Decl(keyofAndIndexedAccess.ts, 45, 19)) + +type Q10 = Shape["name"]; // string +>Q10 : Symbol(Q10, Decl(keyofAndIndexedAccess.ts, 46, 42)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + +type Q11 = Shape["width" | "height"]; // number +>Q11 : Symbol(Q11, Decl(keyofAndIndexedAccess.ts, 48, 25)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + +type Q12 = Shape["name" | "visible"]; // string | boolean +>Q12 : Symbol(Q12, Decl(keyofAndIndexedAccess.ts, 49, 37)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + +type Q20 = Shape[NAME]; // string +>Q20 : Symbol(Q20, Decl(keyofAndIndexedAccess.ts, 50, 37)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) +>NAME : Symbol(NAME, Decl(keyofAndIndexedAccess.ts, 43, 36)) + +type Q21 = Shape[WIDTH_OR_HEIGHT]; // number +>Q21 : Symbol(Q21, Decl(keyofAndIndexedAccess.ts, 52, 23)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) +>WIDTH_OR_HEIGHT : Symbol(WIDTH_OR_HEIGHT, Decl(keyofAndIndexedAccess.ts, 45, 19)) + +type Q30 = [string, number][0]; // string +>Q30 : Symbol(Q30, Decl(keyofAndIndexedAccess.ts, 53, 34)) + +type Q31 = [string, number][1]; // number +>Q31 : Symbol(Q31, Decl(keyofAndIndexedAccess.ts, 55, 31)) + +type Q32 = [string, number][2]; // string | number +>Q32 : Symbol(Q32, Decl(keyofAndIndexedAccess.ts, 56, 31)) + +type Q33 = [string, number][E.A]; // string +>Q33 : Symbol(Q33, Decl(keyofAndIndexedAccess.ts, 57, 31)) +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) +>A : Symbol(E.A, Decl(keyofAndIndexedAccess.ts, 19, 14)) + +type Q34 = [string, number][E.B]; // number +>Q34 : Symbol(Q34, Decl(keyofAndIndexedAccess.ts, 58, 33)) +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) +>B : Symbol(E.B, Decl(keyofAndIndexedAccess.ts, 19, 17)) + +type Q35 = [string, number][E.C]; // string | number +>Q35 : Symbol(Q35, Decl(keyofAndIndexedAccess.ts, 59, 33)) +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) +>C : Symbol(E.C, Decl(keyofAndIndexedAccess.ts, 19, 20)) + +type Q36 = [string, number]["0"]; // string +>Q36 : Symbol(Q36, Decl(keyofAndIndexedAccess.ts, 60, 33)) + +type Q37 = [string, number]["1"]; // string +>Q37 : Symbol(Q37, Decl(keyofAndIndexedAccess.ts, 61, 33)) + +type Q40 = (Shape | Options)["visible"]; // boolean | "yes" | "no" +>Q40 : Symbol(Q40, Decl(keyofAndIndexedAccess.ts, 62, 33)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) +>Options : Symbol(Options, Decl(keyofAndIndexedAccess.ts, 11, 1)) + +type Q41 = (Shape & Options)["visible"]; // true & "yes" | true & "no" | false & "yes" | false & "no" +>Q41 : Symbol(Q41, Decl(keyofAndIndexedAccess.ts, 64, 40)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) +>Options : Symbol(Options, Decl(keyofAndIndexedAccess.ts, 11, 1)) + +type Q50 = Dictionary["howdy"]; // Shape +>Q50 : Symbol(Q50, Decl(keyofAndIndexedAccess.ts, 65, 40)) +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + +type Q51 = Dictionary[123]; // Shape +>Q51 : Symbol(Q51, Decl(keyofAndIndexedAccess.ts, 67, 38)) +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + +type Q52 = Dictionary[E.B]; // Shape +>Q52 : Symbol(Q52, Decl(keyofAndIndexedAccess.ts, 68, 34)) +>Dictionary : Symbol(Dictionary, Decl(keyofAndIndexedAccess.ts, 15, 1)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) +>E : Symbol(E, Decl(keyofAndIndexedAccess.ts, 17, 40)) +>B : Symbol(E.B, Decl(keyofAndIndexedAccess.ts, 19, 17)) + +declare let cond: boolean; +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) + +function getProperty(obj: T, key: K) { +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 73, 21)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 73, 23)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 73, 21)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 73, 43)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 73, 21)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 73, 50)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 73, 23)) + + return obj[key]; +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 73, 43)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 73, 50)) +} + +function setProperty(obj: T, key: K, value: T[K]) { +>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 75, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 77, 21)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 77, 23)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 77, 21)) +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 77, 43)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 77, 21)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 77, 50)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 77, 23)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 77, 58)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 77, 21)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 77, 23)) + + obj[key] = value; +>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 77, 43)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 77, 50)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 77, 58)) +} + +function f10(shape: Shape) { +>f10 : Symbol(f10, Decl(keyofAndIndexedAccess.ts, 79, 1)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + + let name = getProperty(shape, "name"); // string +>name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 82, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) + + let widthOrHeight = getProperty(shape, cond ? "width" : "height"); // number +>widthOrHeight : Symbol(widthOrHeight, Decl(keyofAndIndexedAccess.ts, 83, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) + + let nameOrVisible = getProperty(shape, cond ? "name" : "visible"); // string | boolean +>nameOrVisible : Symbol(nameOrVisible, Decl(keyofAndIndexedAccess.ts, 84, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) + + setProperty(shape, "name", "rectangle"); +>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 75, 1)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) + + setProperty(shape, cond ? "width" : "height", 10); +>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 75, 1)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) + + setProperty(shape, cond ? "name" : "visible", true); // Technically not safe +>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 75, 1)) +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 81, 13)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +} + +function f11(a: Shape[]) { +>f11 : Symbol(f11, Decl(keyofAndIndexedAccess.ts, 88, 1)) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 90, 13)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + + let len = getProperty(a, "length"); // number +>len : Symbol(len, Decl(keyofAndIndexedAccess.ts, 91, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 90, 13)) + + let shape = getProperty(a, 1000); // Shape +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 92, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 90, 13)) + + setProperty(a, 1000, getProperty(a, 1001)); +>setProperty : Symbol(setProperty, Decl(keyofAndIndexedAccess.ts, 75, 1)) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 90, 13)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>a : Symbol(a, Decl(keyofAndIndexedAccess.ts, 90, 13)) +} + +function f12(t: [Shape, boolean]) { +>f12 : Symbol(f12, Decl(keyofAndIndexedAccess.ts, 94, 1)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + + let len = getProperty(t, "length"); +>len : Symbol(len, Decl(keyofAndIndexedAccess.ts, 97, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) + + let s1 = getProperty(t, 0); // Shape +>s1 : Symbol(s1, Decl(keyofAndIndexedAccess.ts, 98, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) + + let s2 = getProperty(t, "0"); // Shape +>s2 : Symbol(s2, Decl(keyofAndIndexedAccess.ts, 99, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) + + let b1 = getProperty(t, 1); // boolean +>b1 : Symbol(b1, Decl(keyofAndIndexedAccess.ts, 100, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) + + let b2 = getProperty(t, "1"); // boolean +>b2 : Symbol(b2, Decl(keyofAndIndexedAccess.ts, 101, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) + + let x1 = getProperty(t, 2); // Shape | boolean +>x1 : Symbol(x1, Decl(keyofAndIndexedAccess.ts, 102, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 96, 13)) +} + +function f13(foo: any, bar: any) { +>f13 : Symbol(f13, Decl(keyofAndIndexedAccess.ts, 103, 1)) +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 105, 13)) +>bar : Symbol(bar, Decl(keyofAndIndexedAccess.ts, 105, 22)) + + let x = getProperty(foo, "x"); // any +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 106, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 105, 13)) + + let y = getProperty(foo, 100); // any +>y : Symbol(y, Decl(keyofAndIndexedAccess.ts, 107, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 105, 13)) + + let z = getProperty(foo, bar); // any +>z : Symbol(z, Decl(keyofAndIndexedAccess.ts, 108, 7)) +>getProperty : Symbol(getProperty, Decl(keyofAndIndexedAccess.ts, 71, 26)) +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 105, 13)) +>bar : Symbol(bar, Decl(keyofAndIndexedAccess.ts, 105, 22)) +} + +class Component { +>Component : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 109, 1)) +>PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 111, 16)) + + props: PropType; +>props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 111, 27)) +>PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 111, 16)) + + getProperty(key: K) { +>getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 113, 16)) +>PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 111, 16)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 113, 42)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 113, 16)) + + return this.props[key]; +>this.props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 111, 27)) +>this : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 109, 1)) +>props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 111, 27)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 113, 42)) + } + setProperty(key: K, value: PropType[K]) { +>setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 116, 16)) +>PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 111, 16)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 116, 42)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 116, 16)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 116, 49)) +>PropType : Symbol(PropType, Decl(keyofAndIndexedAccess.ts, 111, 16)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 116, 16)) + + this.props[key] = value; +>this.props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 111, 27)) +>this : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 109, 1)) +>props : Symbol(Component.props, Decl(keyofAndIndexedAccess.ts, 111, 27)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 116, 42)) +>value : Symbol(value, Decl(keyofAndIndexedAccess.ts, 116, 49)) + } +} + +function f20(component: Component) { +>f20 : Symbol(f20, Decl(keyofAndIndexedAccess.ts, 119, 1)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) +>Component : Symbol(Component, Decl(keyofAndIndexedAccess.ts, 109, 1)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + + let name = component.getProperty("name"); // string +>name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 122, 7)) +>component.getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) +>getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) + + let widthOrHeight = component.getProperty(cond ? "width" : "height"); // number +>widthOrHeight : Symbol(widthOrHeight, Decl(keyofAndIndexedAccess.ts, 123, 7)) +>component.getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) +>getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) + + let nameOrVisible = component.getProperty(cond ? "name" : "visible"); // string | boolean +>nameOrVisible : Symbol(nameOrVisible, Decl(keyofAndIndexedAccess.ts, 124, 7)) +>component.getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) +>getProperty : Symbol(Component.getProperty, Decl(keyofAndIndexedAccess.ts, 112, 20)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) + + component.setProperty("name", "rectangle"); +>component.setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) +>setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) + + component.setProperty(cond ? "width" : "height", 10) +>component.setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) +>setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) + + component.setProperty(cond ? "name" : "visible", true); // Technically not safe +>component.setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) +>component : Symbol(component, Decl(keyofAndIndexedAccess.ts, 121, 13)) +>setProperty : Symbol(Component.setProperty, Decl(keyofAndIndexedAccess.ts, 115, 5)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +} + +function pluck(array: T[], key: K) { +>pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 128, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 130, 15)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 130, 17)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 130, 15)) +>array : Symbol(array, Decl(keyofAndIndexedAccess.ts, 130, 37)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 130, 15)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 130, 48)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 130, 17)) + + return array.map(x => x[key]); +>array.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>array : Symbol(array, Decl(keyofAndIndexedAccess.ts, 130, 37)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 131, 21)) +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 131, 21)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 130, 48)) +} + +function f30(shapes: Shape[]) { +>f30 : Symbol(f30, Decl(keyofAndIndexedAccess.ts, 132, 1)) +>shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 134, 13)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) + + let names = pluck(shapes, "name"); // string[] +>names : Symbol(names, Decl(keyofAndIndexedAccess.ts, 135, 7)) +>pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 128, 1)) +>shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 134, 13)) + + let widths = pluck(shapes, "width"); // number[] +>widths : Symbol(widths, Decl(keyofAndIndexedAccess.ts, 136, 7)) +>pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 128, 1)) +>shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 134, 13)) + + let nameOrVisibles = pluck(shapes, cond ? "name" : "visible"); // (string | boolean)[] +>nameOrVisibles : Symbol(nameOrVisibles, Decl(keyofAndIndexedAccess.ts, 137, 7)) +>pluck : Symbol(pluck, Decl(keyofAndIndexedAccess.ts, 128, 1)) +>shapes : Symbol(shapes, Decl(keyofAndIndexedAccess.ts, 134, 13)) +>cond : Symbol(cond, Decl(keyofAndIndexedAccess.ts, 71, 11)) +} + +function f31(key: K) { +>f31 : Symbol(f31, Decl(keyofAndIndexedAccess.ts, 138, 1)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 140, 13)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 140, 36)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 140, 13)) + + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 141, 9)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) +>name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 141, 26)) +>width : Symbol(width, Decl(keyofAndIndexedAccess.ts, 141, 39)) +>height : Symbol(height, Decl(keyofAndIndexedAccess.ts, 141, 49)) +>visible : Symbol(visible, Decl(keyofAndIndexedAccess.ts, 141, 61)) + + return shape[key]; // Shape[K] +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 141, 9)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 140, 36)) +} + +function f32(key: K) { +>f32 : Symbol(f32, Decl(keyofAndIndexedAccess.ts, 143, 1)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 145, 13)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 145, 43)) +>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 145, 13)) + + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 146, 9)) +>Shape : Symbol(Shape, Decl(keyofAndIndexedAccess.ts, 0, 0)) +>name : Symbol(name, Decl(keyofAndIndexedAccess.ts, 146, 26)) +>width : Symbol(width, Decl(keyofAndIndexedAccess.ts, 146, 39)) +>height : Symbol(height, Decl(keyofAndIndexedAccess.ts, 146, 49)) +>visible : Symbol(visible, Decl(keyofAndIndexedAccess.ts, 146, 61)) + + return shape[key]; // Shape[K] +>shape : Symbol(shape, Decl(keyofAndIndexedAccess.ts, 146, 9)) +>key : Symbol(key, Decl(keyofAndIndexedAccess.ts, 145, 43)) +} + +class C { +>C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 148, 1)) + + public x: string; +>x : Symbol(C.x, Decl(keyofAndIndexedAccess.ts, 150, 9)) + + protected y: string; +>y : Symbol(C.y, Decl(keyofAndIndexedAccess.ts, 151, 21)) + + private z: string; +>z : Symbol(C.z, Decl(keyofAndIndexedAccess.ts, 152, 24)) +} + +// 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) { +>f40 : Symbol(f40, Decl(keyofAndIndexedAccess.ts, 154, 1)) +>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 158, 13)) +>C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 148, 1)) + + type X = C["x"]; +>X : Symbol(X, Decl(keyofAndIndexedAccess.ts, 158, 20)) +>C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 148, 1)) + + type Y = C["y"]; +>Y : Symbol(Y, Decl(keyofAndIndexedAccess.ts, 159, 20)) +>C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 148, 1)) + + type Z = C["z"]; +>Z : Symbol(Z, Decl(keyofAndIndexedAccess.ts, 160, 20)) +>C : Symbol(C, Decl(keyofAndIndexedAccess.ts, 148, 1)) + + let x: X = c["x"]; +>x : Symbol(x, Decl(keyofAndIndexedAccess.ts, 162, 7)) +>X : Symbol(X, Decl(keyofAndIndexedAccess.ts, 158, 20)) +>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 158, 13)) +>"x" : Symbol(C.x, Decl(keyofAndIndexedAccess.ts, 150, 9)) + + let y: Y = c["y"]; +>y : Symbol(y, Decl(keyofAndIndexedAccess.ts, 163, 7)) +>Y : Symbol(Y, Decl(keyofAndIndexedAccess.ts, 159, 20)) +>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 158, 13)) +>"y" : Symbol(C.y, Decl(keyofAndIndexedAccess.ts, 151, 21)) + + let z: Z = c["z"]; +>z : Symbol(z, Decl(keyofAndIndexedAccess.ts, 164, 7)) +>Z : Symbol(Z, Decl(keyofAndIndexedAccess.ts, 160, 20)) +>c : Symbol(c, Decl(keyofAndIndexedAccess.ts, 158, 13)) +>"z" : Symbol(C.z, Decl(keyofAndIndexedAccess.ts, 152, 24)) +} diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types new file mode 100644 index 00000000000..74c06a2535d --- /dev/null +++ b/tests/baselines/reference/keyofAndIndexedAccess.types @@ -0,0 +1,681 @@ +=== tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts === + +class Shape { +>Shape : Shape + + name: string; +>name : string + + width: number; +>width : number + + height: number; +>height : number + + visible: boolean; +>visible : boolean +} + +class Item { +>Item : Item + + name: string; +>name : string + + price: number; +>price : number +} + +class Options { +>Options : Options + + visible: "yes" | "no"; +>visible : "yes" | "no" +} + +type Dictionary = { [x: string]: T }; +>Dictionary : { [x: string]: T; } +>T : T +>x : string +>T : T + +const enum E { A, B, C } +>E : E +>A : E.A +>B : E.B +>C : E.C + +type K00 = keyof any; // string | number +>K00 : string | number + +type K01 = keyof string; // number | "toString" | "charAt" | ... +>K01 : number | "length" | "toString" | "concat" | "slice" | "indexOf" | "lastIndexOf" | "charAt" | "charCodeAt" | "localeCompare" | "match" | "replace" | "search" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "substr" | "valueOf" + +type K02 = keyof number; // "toString" | "toFixed" | "toExponential" | ... +>K02 : "toString" | "toLocaleString" | "valueOf" | "toFixed" | "toExponential" | "toPrecision" + +type K03 = keyof boolean; // "valueOf" +>K03 : "valueOf" + +type K04 = keyof void; // never +>K04 : never + +type K05 = keyof undefined; // never +>K05 : never + +type K06 = keyof null; // never +>K06 : never +>null : null + +type K07 = keyof never; // never +>K07 : never + +type K10 = keyof Shape; // "name" | "width" | "height" | "visible" +>K10 : "name" | "width" | "height" | "visible" +>Shape : Shape + +type K11 = keyof Shape[]; // number | "length" | "toString" | ... +>K11 : number | "length" | "toString" | "toLocaleString" | "push" | "pop" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight" +>Shape : Shape + +type K12 = keyof Dictionary; // string | number +>K12 : string | number +>Dictionary : { [x: string]: T; } +>Shape : Shape + +type K13 = keyof {}; // never +>K13 : never + +type K14 = keyof Object; // "constructor" | "toString" | ... +>K14 : "toString" | "toLocaleString" | "valueOf" | "constructor" | "hasOwnProperty" | "isPrototypeOf" | "propertyIsEnumerable" +>Object : Object + +type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ... +>K15 : "toString" | "toLocaleString" | "valueOf" | "toFixed" | "toExponential" | "toPrecision" +>E : E + +type K16 = keyof [string, number]; // number | "0" | "1" | "length" | "toString" | ... +>K16 : number | "0" | "1" | "length" | "toString" | "toLocaleString" | "push" | "pop" | "concat" | "join" | "reverse" | "shift" | "slice" | "sort" | "splice" | "unshift" | "indexOf" | "lastIndexOf" | "every" | "some" | "forEach" | "map" | "filter" | "reduce" | "reduceRight" + +type K17 = keyof (Shape | Item); // "name" +>K17 : "name" +>Shape : Shape +>Item : Item + +type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "price" +>K18 : "name" | "width" | "height" | "visible" | "price" +>Shape : Shape +>Item : Item + +type KeyOf = keyof T; +>KeyOf : keyof T +>T : T +>T : T + +type K20 = KeyOf; // "name" | "width" | "height" | "visible" +>K20 : "name" | "width" | "height" | "visible" +>KeyOf : keyof T +>Shape : Shape + +type K21 = KeyOf>; // string | number +>K21 : string | number +>KeyOf : keyof T +>Dictionary : { [x: string]: T; } +>Shape : Shape + +type NAME = "name"; +>NAME : "name" + +type WIDTH_OR_HEIGHT = "width" | "height"; +>WIDTH_OR_HEIGHT : "width" | "height" + +type Q10 = Shape["name"]; // string +>Q10 : string +>Shape : Shape + +type Q11 = Shape["width" | "height"]; // number +>Q11 : number +>Shape : Shape + +type Q12 = Shape["name" | "visible"]; // string | boolean +>Q12 : string | boolean +>Shape : Shape + +type Q20 = Shape[NAME]; // string +>Q20 : string +>Shape : Shape +>NAME : "name" + +type Q21 = Shape[WIDTH_OR_HEIGHT]; // number +>Q21 : number +>Shape : Shape +>WIDTH_OR_HEIGHT : "width" | "height" + +type Q30 = [string, number][0]; // string +>Q30 : string + +type Q31 = [string, number][1]; // number +>Q31 : number + +type Q32 = [string, number][2]; // string | number +>Q32 : string | number + +type Q33 = [string, number][E.A]; // string +>Q33 : string +>E : any +>A : E.A + +type Q34 = [string, number][E.B]; // number +>Q34 : number +>E : any +>B : E.B + +type Q35 = [string, number][E.C]; // string | number +>Q35 : string | number +>E : any +>C : E.C + +type Q36 = [string, number]["0"]; // string +>Q36 : string + +type Q37 = [string, number]["1"]; // string +>Q37 : number + +type Q40 = (Shape | Options)["visible"]; // boolean | "yes" | "no" +>Q40 : boolean | "yes" | "no" +>Shape : Shape +>Options : Options + +type Q41 = (Shape & Options)["visible"]; // true & "yes" | true & "no" | false & "yes" | false & "no" +>Q41 : (true & "yes") | (true & "no") | (false & "yes") | (false & "no") +>Shape : Shape +>Options : Options + +type Q50 = Dictionary["howdy"]; // Shape +>Q50 : Shape +>Dictionary : { [x: string]: T; } +>Shape : Shape + +type Q51 = Dictionary[123]; // Shape +>Q51 : Shape +>Dictionary : { [x: string]: T; } +>Shape : Shape + +type Q52 = Dictionary[E.B]; // Shape +>Q52 : Shape +>Dictionary : { [x: string]: T; } +>Shape : Shape +>E : any +>B : E.B + +declare let cond: boolean; +>cond : boolean + +function getProperty(obj: T, key: K) { +>getProperty : (obj: T, key: K) => T[K] +>T : T +>K : K +>T : T +>obj : T +>T : T +>key : K +>K : K + + return obj[key]; +>obj[key] : T[K] +>obj : T +>key : K +} + +function setProperty(obj: T, key: K, value: T[K]) { +>setProperty : (obj: T, key: K, value: T[K]) => void +>T : T +>K : K +>T : T +>obj : T +>T : T +>key : K +>K : K +>value : T[K] +>T : T +>K : K + + obj[key] = value; +>obj[key] = value : T[K] +>obj[key] : T[K] +>obj : T +>key : K +>value : T[K] +} + +function f10(shape: Shape) { +>f10 : (shape: Shape) => void +>shape : Shape +>Shape : Shape + + let name = getProperty(shape, "name"); // string +>name : string +>getProperty(shape, "name") : string +>getProperty : (obj: T, key: K) => T[K] +>shape : Shape +>"name" : "name" + + let widthOrHeight = getProperty(shape, cond ? "width" : "height"); // number +>widthOrHeight : number +>getProperty(shape, cond ? "width" : "height") : number +>getProperty : (obj: T, key: K) => T[K] +>shape : Shape +>cond ? "width" : "height" : "width" | "height" +>cond : boolean +>"width" : "width" +>"height" : "height" + + let nameOrVisible = getProperty(shape, cond ? "name" : "visible"); // string | boolean +>nameOrVisible : string | boolean +>getProperty(shape, cond ? "name" : "visible") : string | boolean +>getProperty : (obj: T, key: K) => T[K] +>shape : Shape +>cond ? "name" : "visible" : "name" | "visible" +>cond : boolean +>"name" : "name" +>"visible" : "visible" + + setProperty(shape, "name", "rectangle"); +>setProperty(shape, "name", "rectangle") : void +>setProperty : (obj: T, key: K, value: T[K]) => void +>shape : Shape +>"name" : "name" +>"rectangle" : "rectangle" + + setProperty(shape, cond ? "width" : "height", 10); +>setProperty(shape, cond ? "width" : "height", 10) : void +>setProperty : (obj: T, key: K, value: T[K]) => void +>shape : Shape +>cond ? "width" : "height" : "width" | "height" +>cond : boolean +>"width" : "width" +>"height" : "height" +>10 : 10 + + setProperty(shape, cond ? "name" : "visible", true); // Technically not safe +>setProperty(shape, cond ? "name" : "visible", true) : void +>setProperty : (obj: T, key: K, value: T[K]) => void +>shape : Shape +>cond ? "name" : "visible" : "name" | "visible" +>cond : boolean +>"name" : "name" +>"visible" : "visible" +>true : true +} + +function f11(a: Shape[]) { +>f11 : (a: Shape[]) => void +>a : Shape[] +>Shape : Shape + + let len = getProperty(a, "length"); // number +>len : number +>getProperty(a, "length") : number +>getProperty : (obj: T, key: K) => T[K] +>a : Shape[] +>"length" : "length" + + let shape = getProperty(a, 1000); // Shape +>shape : Shape +>getProperty(a, 1000) : Shape +>getProperty : (obj: T, key: K) => T[K] +>a : Shape[] +>1000 : 1000 + + setProperty(a, 1000, getProperty(a, 1001)); +>setProperty(a, 1000, getProperty(a, 1001)) : void +>setProperty : (obj: T, key: K, value: T[K]) => void +>a : Shape[] +>1000 : 1000 +>getProperty(a, 1001) : Shape +>getProperty : (obj: T, key: K) => T[K] +>a : Shape[] +>1001 : 1001 +} + +function f12(t: [Shape, boolean]) { +>f12 : (t: [Shape, boolean]) => void +>t : [Shape, boolean] +>Shape : Shape + + let len = getProperty(t, "length"); +>len : number +>getProperty(t, "length") : number +>getProperty : (obj: T, key: K) => T[K] +>t : [Shape, boolean] +>"length" : "length" + + let s1 = getProperty(t, 0); // Shape +>s1 : Shape +>getProperty(t, 0) : Shape +>getProperty : (obj: T, key: K) => T[K] +>t : [Shape, boolean] +>0 : 0 + + let s2 = getProperty(t, "0"); // Shape +>s2 : Shape +>getProperty(t, "0") : Shape +>getProperty : (obj: T, key: K) => T[K] +>t : [Shape, boolean] +>"0" : "0" + + let b1 = getProperty(t, 1); // boolean +>b1 : boolean +>getProperty(t, 1) : boolean +>getProperty : (obj: T, key: K) => T[K] +>t : [Shape, boolean] +>1 : 1 + + let b2 = getProperty(t, "1"); // boolean +>b2 : boolean +>getProperty(t, "1") : boolean +>getProperty : (obj: T, key: K) => T[K] +>t : [Shape, boolean] +>"1" : "1" + + let x1 = getProperty(t, 2); // Shape | boolean +>x1 : boolean | Shape +>getProperty(t, 2) : boolean | Shape +>getProperty : (obj: T, key: K) => T[K] +>t : [Shape, boolean] +>2 : 2 +} + +function f13(foo: any, bar: any) { +>f13 : (foo: any, bar: any) => void +>foo : any +>bar : any + + let x = getProperty(foo, "x"); // any +>x : any +>getProperty(foo, "x") : any +>getProperty : (obj: T, key: K) => T[K] +>foo : any +>"x" : "x" + + let y = getProperty(foo, 100); // any +>y : any +>getProperty(foo, 100) : any +>getProperty : (obj: T, key: K) => T[K] +>foo : any +>100 : 100 + + let z = getProperty(foo, bar); // any +>z : any +>getProperty(foo, bar) : any +>getProperty : (obj: T, key: K) => T[K] +>foo : any +>bar : any +} + +class Component { +>Component : Component +>PropType : PropType + + props: PropType; +>props : PropType +>PropType : PropType + + getProperty(key: K) { +>getProperty : (key: K) => PropType[K] +>K : K +>PropType : PropType +>key : K +>K : K + + return this.props[key]; +>this.props[key] : PropType[K] +>this.props : PropType +>this : this +>props : PropType +>key : K + } + setProperty(key: K, value: PropType[K]) { +>setProperty : (key: K, value: PropType[K]) => void +>K : K +>PropType : PropType +>key : K +>K : K +>value : PropType[K] +>PropType : PropType +>K : K + + this.props[key] = value; +>this.props[key] = value : PropType[K] +>this.props[key] : PropType[K] +>this.props : PropType +>this : this +>props : PropType +>key : K +>value : PropType[K] + } +} + +function f20(component: Component) { +>f20 : (component: Component) => void +>component : Component +>Component : Component +>Shape : Shape + + let name = component.getProperty("name"); // string +>name : string +>component.getProperty("name") : string +>component.getProperty : (key: K) => Shape[K] +>component : Component +>getProperty : (key: K) => Shape[K] +>"name" : "name" + + let widthOrHeight = component.getProperty(cond ? "width" : "height"); // number +>widthOrHeight : number +>component.getProperty(cond ? "width" : "height") : number +>component.getProperty : (key: K) => Shape[K] +>component : Component +>getProperty : (key: K) => Shape[K] +>cond ? "width" : "height" : "width" | "height" +>cond : boolean +>"width" : "width" +>"height" : "height" + + let nameOrVisible = component.getProperty(cond ? "name" : "visible"); // string | boolean +>nameOrVisible : string | boolean +>component.getProperty(cond ? "name" : "visible") : string | boolean +>component.getProperty : (key: K) => Shape[K] +>component : Component +>getProperty : (key: K) => Shape[K] +>cond ? "name" : "visible" : "name" | "visible" +>cond : boolean +>"name" : "name" +>"visible" : "visible" + + component.setProperty("name", "rectangle"); +>component.setProperty("name", "rectangle") : void +>component.setProperty : (key: K, value: Shape[K]) => void +>component : Component +>setProperty : (key: K, value: Shape[K]) => void +>"name" : "name" +>"rectangle" : "rectangle" + + component.setProperty(cond ? "width" : "height", 10) +>component.setProperty(cond ? "width" : "height", 10) : void +>component.setProperty : (key: K, value: Shape[K]) => void +>component : Component +>setProperty : (key: K, value: Shape[K]) => void +>cond ? "width" : "height" : "width" | "height" +>cond : boolean +>"width" : "width" +>"height" : "height" +>10 : 10 + + component.setProperty(cond ? "name" : "visible", true); // Technically not safe +>component.setProperty(cond ? "name" : "visible", true) : void +>component.setProperty : (key: K, value: Shape[K]) => void +>component : Component +>setProperty : (key: K, value: Shape[K]) => void +>cond ? "name" : "visible" : "name" | "visible" +>cond : boolean +>"name" : "name" +>"visible" : "visible" +>true : true +} + +function pluck(array: T[], key: K) { +>pluck : (array: T[], key: K) => T[K][] +>T : T +>K : K +>T : T +>array : T[] +>T : T +>key : K +>K : K + + return array.map(x => x[key]); +>array.map(x => x[key]) : T[K][] +>array.map : { (this: [T, T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U, U]; (this: [T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U]; (this: [T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U]; (this: [T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U]; (callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; } +>array : T[] +>map : { (this: [T, T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U, U]; (this: [T, T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U, U]; (this: [T, T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U, U]; (this: [T, T], callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): [U, U]; (callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; } +>x => x[key] : (x: T) => T[K] +>x : T +>x[key] : T[K] +>x : T +>key : K +} + +function f30(shapes: Shape[]) { +>f30 : (shapes: Shape[]) => void +>shapes : Shape[] +>Shape : Shape + + let names = pluck(shapes, "name"); // string[] +>names : string[] +>pluck(shapes, "name") : string[] +>pluck : (array: T[], key: K) => T[K][] +>shapes : Shape[] +>"name" : "name" + + let widths = pluck(shapes, "width"); // number[] +>widths : number[] +>pluck(shapes, "width") : number[] +>pluck : (array: T[], key: K) => T[K][] +>shapes : Shape[] +>"width" : "width" + + let nameOrVisibles = pluck(shapes, cond ? "name" : "visible"); // (string | boolean)[] +>nameOrVisibles : (string | boolean)[] +>pluck(shapes, cond ? "name" : "visible") : (string | boolean)[] +>pluck : (array: T[], key: K) => T[K][] +>shapes : Shape[] +>cond ? "name" : "visible" : "name" | "visible" +>cond : boolean +>"name" : "name" +>"visible" : "visible" +} + +function f31(key: K) { +>f31 : (key: K) => Shape[K] +>K : K +>Shape : Shape +>key : K +>K : K + + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; +>shape : Shape +>Shape : Shape +>{ name: "foo", width: 5, height: 10, visible: true } : { name: string; width: number; height: number; visible: true; } +>name : string +>"foo" : "foo" +>width : number +>5 : 5 +>height : number +>10 : 10 +>visible : boolean +>true : true + + return shape[key]; // Shape[K] +>shape[key] : Shape[K] +>shape : Shape +>key : K +} + +function f32(key: K) { +>f32 : (key: K) => Shape[K] +>K : K +>key : K +>K : K + + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; +>shape : Shape +>Shape : Shape +>{ name: "foo", width: 5, height: 10, visible: true } : { name: string; width: number; height: number; visible: true; } +>name : string +>"foo" : "foo" +>width : number +>5 : 5 +>height : number +>10 : 10 +>visible : boolean +>true : true + + return shape[key]; // Shape[K] +>shape[key] : Shape[K] +>shape : Shape +>key : K +} + +class C { +>C : C + + public x: string; +>x : string + + protected y: string; +>y : string + + private z: string; +>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) { +>f40 : (c: C) => void +>c : C +>C : C + + type X = C["x"]; +>X : string +>C : C + + type Y = C["y"]; +>Y : string +>C : C + + type Z = C["z"]; +>Z : string +>C : C + + let x: X = c["x"]; +>x : string +>X : string +>c["x"] : string +>c : C +>"x" : "x" + + let y: Y = c["y"]; +>y : string +>Y : string +>c["y"] : string +>c : C +>"y" : "y" + + let z: Z = c["z"]; +>z : string +>Z : string +>c["z"] : string +>c : C +>"z" : "z" +} diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt b/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt new file mode 100644 index 00000000000..23b79c16627 --- /dev/null +++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.errors.txt @@ -0,0 +1,138 @@ +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(10,18): error TS2304: Cannot find name 'K0'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(20,18): error TS2339: Property 'foo' does not exist on type 'Shape'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(21,18): error TS2339: Property 'foo' does not exist on type 'Shape'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(22,18): error TS2538: Type 'any' cannot be used as an index type. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(23,18): error TS2537: Type 'Shape' has no matching index signature for type 'string'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(24,18): error TS2537: Type 'Shape' has no matching index signature for type 'number'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(25,18): error TS2538: Type 'boolean' cannot be used as an index type. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(26,18): error TS2538: Type 'void' cannot be used as an index type. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(27,18): error TS2538: Type 'undefined' cannot be used as an index type. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(28,18): error TS2538: Type '{ x: string; }' cannot be used as an index type. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(29,18): error TS2537: Type 'Shape' has no matching index signature for type 'string'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(30,18): error TS2538: Type 'string & number' cannot be used as an index type. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(31,18): error TS2537: Type 'Shape' has no matching index signature for type 'string'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(35,21): error TS2537: Type 'string[]' has no matching index signature for type 'string'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(36,21): error TS2538: Type 'boolean' cannot be used as an index type. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(41,31): error TS2538: Type 'boolean' cannot be used as an index type. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(46,16): error TS2538: Type 'boolean' cannot be used as an index type. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(63,33): error TS2345: Argument of type '"size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(64,33): error TS2345: Argument of type '"name" | "size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'. + Type '"size"' is not assignable to type '"name" | "width" | "height" | "visible"'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(66,24): error TS2345: Argument of type '"size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'. +tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(67,24): error TS2345: Argument of type '"name" | "size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'. + Type '"size"' is not assignable to type '"name" | "width" | "height" | "visible"'. + + +==== tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts (21 errors) ==== + class Shape { + name: string; + width: number; + height: number; + visible: boolean; + } + + type Dictionary = { [x: string]: T }; + + type T00 = keyof K0; // Error + ~~ +!!! error TS2304: Cannot find name 'K0'. + + type T01 = keyof Object; + type T02 = keyof keyof Object; + type T03 = keyof keyof keyof Object; + type T04 = keyof keyof keyof keyof Object; + type T05 = keyof keyof keyof keyof keyof Object; + type T06 = keyof keyof keyof keyof keyof keyof Object; + + type T10 = Shape["name"]; + type T11 = Shape["foo"]; // Error + ~~~~~ +!!! error TS2339: Property 'foo' does not exist on type 'Shape'. + type T12 = Shape["name" | "foo"]; // Error + ~~~~~~~~~~~~~~ +!!! error TS2339: Property 'foo' does not exist on type 'Shape'. + type T13 = Shape[any]; // Error + ~~~ +!!! error TS2538: Type 'any' cannot be used as an index type. + type T14 = Shape[string]; // Error + ~~~~~~ +!!! error TS2537: Type 'Shape' has no matching index signature for type 'string'. + type T15 = Shape[number]; // Error + ~~~~~~ +!!! error TS2537: Type 'Shape' has no matching index signature for type 'number'. + type T16 = Shape[boolean]; // Error + ~~~~~~~ +!!! error TS2538: Type 'boolean' cannot be used as an index type. + type T17 = Shape[void]; // Error + ~~~~ +!!! error TS2538: Type 'void' cannot be used as an index type. + type T18 = Shape[undefined]; // Error + ~~~~~~~~~ +!!! error TS2538: Type 'undefined' cannot be used as an index type. + type T19 = Shape[{ x: string }]; // Error + ~~~~~~~~~~~~~ +!!! error TS2538: Type '{ x: string; }' cannot be used as an index type. + type T20 = Shape[string | number]; // Error + ~~~~~~~~~~~~~~~ +!!! error TS2537: Type 'Shape' has no matching index signature for type 'string'. + type T21 = Shape[string & number]; // Error + ~~~~~~~~~~~~~~~ +!!! error TS2538: Type 'string & number' cannot be used as an index type. + type T22 = Shape[string | boolean]; // Error + ~~~~~~~~~~~~~~~~ +!!! error TS2537: Type 'Shape' has no matching index signature for type 'string'. + + type T30 = string[]["length"]; + type T31 = string[][number]; + type T32 = string[][string]; // Error + ~~~~~~ +!!! error TS2537: Type 'string[]' has no matching index signature for type 'string'. + type T33 = string[][boolean]; // Error + ~~~~~~~ +!!! error TS2538: Type 'boolean' cannot be used as an index type. + + type T40 = Dictionary[any]; + type T41 = Dictionary[number]; + type T42 = Dictionary[string]; + type T43 = Dictionary[boolean]; // Error + ~~~~~~~ +!!! error TS2538: Type 'boolean' cannot be used as an index type. + + type T50 = any[any]; + type T51 = any[number]; + type T52 = any[string]; + type T53 = any[boolean]; // Error + ~~~~~~~ +!!! error TS2538: Type 'boolean' cannot be used as an index type. + + type T60 = {}["toString"]; + type T61 = []["toString"]; + + declare let cond: boolean; + + function getProperty(obj: T, key: K) { + return obj[key]; + } + + function setProperty(obj: T, key: K, value: T[K]) { + obj[key] = value; + } + + function f10(shape: Shape) { + let x1 = getProperty(shape, "name"); + let x2 = getProperty(shape, "size"); // Error + ~~~~~~ +!!! error TS2345: Argument of type '"size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'. + let x3 = getProperty(shape, cond ? "name" : "size"); // Error + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '"name" | "size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'. +!!! error TS2345: Type '"size"' is not assignable to type '"name" | "width" | "height" | "visible"'. + setProperty(shape, "name", "rectangle"); + setProperty(shape, "size", 10); // Error + ~~~~~~ +!!! error TS2345: Argument of type '"size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'. + setProperty(shape, cond ? "name" : "size", 10); // Error + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '"name" | "size"' is not assignable to parameter of type '"name" | "width" | "height" | "visible"'. +!!! error TS2345: Type '"size"' is not assignable to type '"name" | "width" | "height" | "visible"'. + } \ No newline at end of file diff --git a/tests/baselines/reference/keyofAndIndexedAccessErrors.js b/tests/baselines/reference/keyofAndIndexedAccessErrors.js new file mode 100644 index 00000000000..145d8e3f148 --- /dev/null +++ b/tests/baselines/reference/keyofAndIndexedAccessErrors.js @@ -0,0 +1,90 @@ +//// [keyofAndIndexedAccessErrors.ts] +class Shape { + name: string; + width: number; + height: number; + visible: boolean; +} + +type Dictionary = { [x: string]: T }; + +type T00 = keyof K0; // Error + +type T01 = keyof Object; +type T02 = keyof keyof Object; +type T03 = keyof keyof keyof Object; +type T04 = keyof keyof keyof keyof Object; +type T05 = keyof keyof keyof keyof keyof Object; +type T06 = keyof keyof keyof keyof keyof keyof Object; + +type T10 = Shape["name"]; +type T11 = Shape["foo"]; // Error +type T12 = Shape["name" | "foo"]; // Error +type T13 = Shape[any]; // Error +type T14 = Shape[string]; // Error +type T15 = Shape[number]; // Error +type T16 = Shape[boolean]; // Error +type T17 = Shape[void]; // Error +type T18 = Shape[undefined]; // Error +type T19 = Shape[{ x: string }]; // Error +type T20 = Shape[string | number]; // Error +type T21 = Shape[string & number]; // Error +type T22 = Shape[string | boolean]; // Error + +type T30 = string[]["length"]; +type T31 = string[][number]; +type T32 = string[][string]; // Error +type T33 = string[][boolean]; // Error + +type T40 = Dictionary[any]; +type T41 = Dictionary[number]; +type T42 = Dictionary[string]; +type T43 = Dictionary[boolean]; // Error + +type T50 = any[any]; +type T51 = any[number]; +type T52 = any[string]; +type T53 = any[boolean]; // Error + +type T60 = {}["toString"]; +type T61 = []["toString"]; + +declare let cond: boolean; + +function getProperty(obj: T, key: K) { + return obj[key]; +} + +function setProperty(obj: T, key: K, value: T[K]) { + obj[key] = value; +} + +function f10(shape: Shape) { + let x1 = getProperty(shape, "name"); + let x2 = getProperty(shape, "size"); // Error + let x3 = getProperty(shape, cond ? "name" : "size"); // Error + setProperty(shape, "name", "rectangle"); + setProperty(shape, "size", 10); // Error + setProperty(shape, cond ? "name" : "size", 10); // Error +} + +//// [keyofAndIndexedAccessErrors.js] +var Shape = (function () { + function Shape() { + } + return Shape; +}()); +function getProperty(obj, key) { + return obj[key]; +} +function setProperty(obj, key, value) { + obj[key] = value; +} +function f10(shape) { + var x1 = getProperty(shape, "name"); + var x2 = getProperty(shape, "size"); // Error + var x3 = getProperty(shape, cond ? "name" : "size"); // Error + setProperty(shape, "name", "rectangle"); + setProperty(shape, "size", 10); // Error + setProperty(shape, cond ? "name" : "size", 10); // Error +} diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts new file mode 100644 index 00000000000..b63386a68a3 --- /dev/null +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts @@ -0,0 +1,167 @@ +// @declaration: true + +class Shape { + name: string; + width: number; + height: number; + visible: boolean; +} + +class Item { + name: string; + price: number; +} + +class Options { + visible: "yes" | "no"; +} + +type Dictionary = { [x: string]: T }; + +const enum E { A, B, C } + +type K00 = keyof any; // string | number +type K01 = keyof string; // number | "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[]; // number | "length" | "toString" | ... +type K12 = keyof Dictionary; // string | number +type K13 = keyof {}; // never +type K14 = keyof Object; // "constructor" | "toString" | ... +type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ... +type K16 = keyof [string, number]; // number | "0" | "1" | "length" | "toString" | ... +type K17 = keyof (Shape | Item); // "name" +type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "price" + +type KeyOf = keyof T; + +type K20 = KeyOf; // "name" | "width" | "height" | "visible" +type K21 = KeyOf>; // string | number + +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["howdy"]; // Shape +type Q51 = Dictionary[123]; // Shape +type Q52 = Dictionary[E.B]; // Shape + +declare let cond: boolean; + +function getProperty(obj: T, key: K) { + return obj[key]; +} + +function setProperty(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 + let shape = getProperty(a, 1000); // Shape + setProperty(a, 1000, getProperty(a, 1001)); +} + +function f12(t: [Shape, boolean]) { + let len = getProperty(t, "length"); + let s1 = getProperty(t, 0); // Shape + let s2 = getProperty(t, "0"); // Shape + let b1 = getProperty(t, 1); // boolean + let b2 = getProperty(t, "1"); // boolean + let x1 = getProperty(t, 2); // Shape | 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 { + props: PropType; + getProperty(key: K) { + return this.props[key]; + } + setProperty(key: K, value: PropType[K]) { + this.props[key] = value; + } +} + +function f20(component: Component) { + 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(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(key: K) { + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; + return shape[key]; // Shape[K] +} + +function f32(key: K) { + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; + return shape[key]; // Shape[K] +} + +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"]; +} \ No newline at end of file diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts new file mode 100644 index 00000000000..bc2ddc31a19 --- /dev/null +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts @@ -0,0 +1,68 @@ +class Shape { + name: string; + width: number; + height: number; + visible: boolean; +} + +type Dictionary = { [x: string]: T }; + +type T00 = keyof K0; // Error + +type T01 = keyof Object; +type T02 = keyof keyof Object; +type T03 = keyof keyof keyof Object; +type T04 = keyof keyof keyof keyof Object; +type T05 = keyof keyof keyof keyof keyof Object; +type T06 = keyof keyof keyof keyof keyof keyof Object; + +type T10 = Shape["name"]; +type T11 = Shape["foo"]; // Error +type T12 = Shape["name" | "foo"]; // Error +type T13 = Shape[any]; // Error +type T14 = Shape[string]; // Error +type T15 = Shape[number]; // Error +type T16 = Shape[boolean]; // Error +type T17 = Shape[void]; // Error +type T18 = Shape[undefined]; // Error +type T19 = Shape[{ x: string }]; // Error +type T20 = Shape[string | number]; // Error +type T21 = Shape[string & number]; // Error +type T22 = Shape[string | boolean]; // Error + +type T30 = string[]["length"]; +type T31 = string[][number]; +type T32 = string[][string]; // Error +type T33 = string[][boolean]; // Error + +type T40 = Dictionary[any]; +type T41 = Dictionary[number]; +type T42 = Dictionary[string]; +type T43 = Dictionary[boolean]; // Error + +type T50 = any[any]; +type T51 = any[number]; +type T52 = any[string]; +type T53 = any[boolean]; // Error + +type T60 = {}["toString"]; +type T61 = []["toString"]; + +declare let cond: boolean; + +function getProperty(obj: T, key: K) { + return obj[key]; +} + +function setProperty(obj: T, key: K, value: T[K]) { + obj[key] = value; +} + +function f10(shape: Shape) { + let x1 = getProperty(shape, "name"); + let x2 = getProperty(shape, "size"); // Error + let x3 = getProperty(shape, cond ? "name" : "size"); // Error + setProperty(shape, "name", "rectangle"); + setProperty(shape, "size", 10); // Error + setProperty(shape, cond ? "name" : "size", 10); // Error +} \ No newline at end of file