|
| 1 | +//// [keyofAndIndexedAccess.ts] |
| 2 | + |
| 3 | +class Shape { |
| 4 | + name: string; |
| 5 | + width: number; |
| 6 | + height: number; |
| 7 | + visible: boolean; |
| 8 | +} |
| 9 | + |
| 10 | +class Item { |
| 11 | + name: string; |
| 12 | + price: number; |
| 13 | +} |
| 14 | + |
| 15 | +class Options { |
| 16 | + visible: "yes" | "no"; |
| 17 | +} |
| 18 | + |
| 19 | +type Dictionary<T> = { [x: string]: T }; |
| 20 | + |
| 21 | +const enum E { A, B, C } |
| 22 | + |
| 23 | +type K00 = keyof any; // string | number |
| 24 | +type K01 = keyof string; // number | "toString" | "charAt" | ... |
| 25 | +type K02 = keyof number; // "toString" | "toFixed" | "toExponential" | ... |
| 26 | +type K03 = keyof boolean; // "valueOf" |
| 27 | +type K04 = keyof void; // never |
| 28 | +type K05 = keyof undefined; // never |
| 29 | +type K06 = keyof null; // never |
| 30 | +type K07 = keyof never; // never |
| 31 | + |
| 32 | +type K10 = keyof Shape; // "name" | "width" | "height" | "visible" |
| 33 | +type K11 = keyof Shape[]; // number | "length" | "toString" | ... |
| 34 | +type K12 = keyof Dictionary<Shape>; // string | number |
| 35 | +type K13 = keyof {}; // never |
| 36 | +type K14 = keyof Object; // "constructor" | "toString" | ... |
| 37 | +type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ... |
| 38 | +type K16 = keyof [string, number]; // number | "0" | "1" | "length" | "toString" | ... |
| 39 | +type K17 = keyof (Shape | Item); // "name" |
| 40 | +type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "price" |
| 41 | + |
| 42 | +type KeyOf<T> = keyof T; |
| 43 | + |
| 44 | +type K20 = KeyOf<Shape>; // "name" | "width" | "height" | "visible" |
| 45 | +type K21 = KeyOf<Dictionary<Shape>>; // string | number |
| 46 | + |
| 47 | +type NAME = "name"; |
| 48 | +type WIDTH_OR_HEIGHT = "width" | "height"; |
| 49 | + |
| 50 | +type Q10 = Shape["name"]; // string |
| 51 | +type Q11 = Shape["width" | "height"]; // number |
| 52 | +type Q12 = Shape["name" | "visible"]; // string | boolean |
| 53 | + |
| 54 | +type Q20 = Shape[NAME]; // string |
| 55 | +type Q21 = Shape[WIDTH_OR_HEIGHT]; // number |
| 56 | + |
| 57 | +type Q30 = [string, number][0]; // string |
| 58 | +type Q31 = [string, number][1]; // number |
| 59 | +type Q32 = [string, number][2]; // string | number |
| 60 | +type Q33 = [string, number][E.A]; // string |
| 61 | +type Q34 = [string, number][E.B]; // number |
| 62 | +type Q35 = [string, number][E.C]; // string | number |
| 63 | +type Q36 = [string, number]["0"]; // string |
| 64 | +type Q37 = [string, number]["1"]; // string |
| 65 | + |
| 66 | +type Q40 = (Shape | Options)["visible"]; // boolean | "yes" | "no" |
| 67 | +type Q41 = (Shape & Options)["visible"]; // true & "yes" | true & "no" | false & "yes" | false & "no" |
| 68 | + |
| 69 | +type Q50 = Dictionary<Shape>["howdy"]; // Shape |
| 70 | +type Q51 = Dictionary<Shape>[123]; // Shape |
| 71 | +type Q52 = Dictionary<Shape>[E.B]; // Shape |
| 72 | + |
| 73 | +declare let cond: boolean; |
| 74 | + |
| 75 | +function getProperty<T, K extends keyof T>(obj: T, key: K) { |
| 76 | + return obj[key]; |
| 77 | +} |
| 78 | + |
| 79 | +function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) { |
| 80 | + obj[key] = value; |
| 81 | +} |
| 82 | + |
| 83 | +function f10(shape: Shape) { |
| 84 | + let name = getProperty(shape, "name"); // string |
| 85 | + let widthOrHeight = getProperty(shape, cond ? "width" : "height"); // number |
| 86 | + let nameOrVisible = getProperty(shape, cond ? "name" : "visible"); // string | boolean |
| 87 | + setProperty(shape, "name", "rectangle"); |
| 88 | + setProperty(shape, cond ? "width" : "height", 10); |
| 89 | + setProperty(shape, cond ? "name" : "visible", true); // Technically not safe |
| 90 | +} |
| 91 | + |
| 92 | +function f11(a: Shape[]) { |
| 93 | + let len = getProperty(a, "length"); // number |
| 94 | + let shape = getProperty(a, 1000); // Shape |
| 95 | + setProperty(a, 1000, getProperty(a, 1001)); |
| 96 | +} |
| 97 | + |
| 98 | +function f12(t: [Shape, boolean]) { |
| 99 | + let len = getProperty(t, "length"); |
| 100 | + let s1 = getProperty(t, 0); // Shape |
| 101 | + let s2 = getProperty(t, "0"); // Shape |
| 102 | + let b1 = getProperty(t, 1); // boolean |
| 103 | + let b2 = getProperty(t, "1"); // boolean |
| 104 | + let x1 = getProperty(t, 2); // Shape | boolean |
| 105 | +} |
| 106 | + |
| 107 | +function f13(foo: any, bar: any) { |
| 108 | + let x = getProperty(foo, "x"); // any |
| 109 | + let y = getProperty(foo, 100); // any |
| 110 | + let z = getProperty(foo, bar); // any |
| 111 | +} |
| 112 | + |
| 113 | +class Component<PropType> { |
| 114 | + props: PropType; |
| 115 | + getProperty<K extends keyof PropType>(key: K) { |
| 116 | + return this.props[key]; |
| 117 | + } |
| 118 | + setProperty<K extends keyof PropType>(key: K, value: PropType[K]) { |
| 119 | + this.props[key] = value; |
| 120 | + } |
| 121 | +} |
| 122 | + |
| 123 | +function f20(component: Component<Shape>) { |
| 124 | + let name = component.getProperty("name"); // string |
| 125 | + let widthOrHeight = component.getProperty(cond ? "width" : "height"); // number |
| 126 | + let nameOrVisible = component.getProperty(cond ? "name" : "visible"); // string | boolean |
| 127 | + component.setProperty("name", "rectangle"); |
| 128 | + component.setProperty(cond ? "width" : "height", 10) |
| 129 | + component.setProperty(cond ? "name" : "visible", true); // Technically not safe |
| 130 | +} |
| 131 | + |
| 132 | +function pluck<T, K extends keyof T>(array: T[], key: K) { |
| 133 | + return array.map(x => x[key]); |
| 134 | +} |
| 135 | + |
| 136 | +function f30(shapes: Shape[]) { |
| 137 | + let names = pluck(shapes, "name"); // string[] |
| 138 | + let widths = pluck(shapes, "width"); // number[] |
| 139 | + let nameOrVisibles = pluck(shapes, cond ? "name" : "visible"); // (string | boolean)[] |
| 140 | +} |
| 141 | + |
| 142 | +function f31<K extends keyof Shape>(key: K) { |
| 143 | + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; |
| 144 | + return shape[key]; // Shape[K] |
| 145 | +} |
| 146 | + |
| 147 | +function f32<K extends "width" | "height">(key: K) { |
| 148 | + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; |
| 149 | + return shape[key]; // Shape[K] |
| 150 | +} |
| 151 | + |
| 152 | +class C { |
| 153 | + public x: string; |
| 154 | + protected y: string; |
| 155 | + private z: string; |
| 156 | +} |
| 157 | + |
| 158 | +// Indexed access expressions have always permitted access to private and protected members. |
| 159 | +// For consistency we also permit such access in indexed access types. |
| 160 | +function f40(c: C) { |
| 161 | + type X = C["x"]; |
| 162 | + type Y = C["y"]; |
| 163 | + type Z = C["z"]; |
| 164 | + let x: X = c["x"]; |
| 165 | + let y: Y = c["y"]; |
| 166 | + let z: Z = c["z"]; |
| 167 | +} |
| 168 | + |
| 169 | +//// [keyofAndIndexedAccess.js] |
| 170 | +var Shape = (function () { |
| 171 | + function Shape() { |
| 172 | + } |
| 173 | + return Shape; |
| 174 | +}()); |
| 175 | +var Item = (function () { |
| 176 | + function Item() { |
| 177 | + } |
| 178 | + return Item; |
| 179 | +}()); |
| 180 | +var Options = (function () { |
| 181 | + function Options() { |
| 182 | + } |
| 183 | + return Options; |
| 184 | +}()); |
| 185 | +function getProperty(obj, key) { |
| 186 | + return obj[key]; |
| 187 | +} |
| 188 | +function setProperty(obj, key, value) { |
| 189 | + obj[key] = value; |
| 190 | +} |
| 191 | +function f10(shape) { |
| 192 | + var name = getProperty(shape, "name"); // string |
| 193 | + var widthOrHeight = getProperty(shape, cond ? "width" : "height"); // number |
| 194 | + var nameOrVisible = getProperty(shape, cond ? "name" : "visible"); // string | boolean |
| 195 | + setProperty(shape, "name", "rectangle"); |
| 196 | + setProperty(shape, cond ? "width" : "height", 10); |
| 197 | + setProperty(shape, cond ? "name" : "visible", true); // Technically not safe |
| 198 | +} |
| 199 | +function f11(a) { |
| 200 | + var len = getProperty(a, "length"); // number |
| 201 | + var shape = getProperty(a, 1000); // Shape |
| 202 | + setProperty(a, 1000, getProperty(a, 1001)); |
| 203 | +} |
| 204 | +function f12(t) { |
| 205 | + var len = getProperty(t, "length"); |
| 206 | + var s1 = getProperty(t, 0); // Shape |
| 207 | + var s2 = getProperty(t, "0"); // Shape |
| 208 | + var b1 = getProperty(t, 1); // boolean |
| 209 | + var b2 = getProperty(t, "1"); // boolean |
| 210 | + var x1 = getProperty(t, 2); // Shape | boolean |
| 211 | +} |
| 212 | +function f13(foo, bar) { |
| 213 | + var x = getProperty(foo, "x"); // any |
| 214 | + var y = getProperty(foo, 100); // any |
| 215 | + var z = getProperty(foo, bar); // any |
| 216 | +} |
| 217 | +var Component = (function () { |
| 218 | + function Component() { |
| 219 | + } |
| 220 | + Component.prototype.getProperty = function (key) { |
| 221 | + return this.props[key]; |
| 222 | + }; |
| 223 | + Component.prototype.setProperty = function (key, value) { |
| 224 | + this.props[key] = value; |
| 225 | + }; |
| 226 | + return Component; |
| 227 | +}()); |
| 228 | +function f20(component) { |
| 229 | + var name = component.getProperty("name"); // string |
| 230 | + var widthOrHeight = component.getProperty(cond ? "width" : "height"); // number |
| 231 | + var nameOrVisible = component.getProperty(cond ? "name" : "visible"); // string | boolean |
| 232 | + component.setProperty("name", "rectangle"); |
| 233 | + component.setProperty(cond ? "width" : "height", 10); |
| 234 | + component.setProperty(cond ? "name" : "visible", true); // Technically not safe |
| 235 | +} |
| 236 | +function pluck(array, key) { |
| 237 | + return array.map(function (x) { return x[key]; }); |
| 238 | +} |
| 239 | +function f30(shapes) { |
| 240 | + var names = pluck(shapes, "name"); // string[] |
| 241 | + var widths = pluck(shapes, "width"); // number[] |
| 242 | + var nameOrVisibles = pluck(shapes, cond ? "name" : "visible"); // (string | boolean)[] |
| 243 | +} |
| 244 | +function f31(key) { |
| 245 | + var shape = { name: "foo", width: 5, height: 10, visible: true }; |
| 246 | + return shape[key]; // Shape[K] |
| 247 | +} |
| 248 | +function f32(key) { |
| 249 | + var shape = { name: "foo", width: 5, height: 10, visible: true }; |
| 250 | + return shape[key]; // Shape[K] |
| 251 | +} |
| 252 | +var C = (function () { |
| 253 | + function C() { |
| 254 | + } |
| 255 | + return C; |
| 256 | +}()); |
| 257 | +// Indexed access expressions have always permitted access to private and protected members. |
| 258 | +// For consistency we also permit such access in indexed access types. |
| 259 | +function f40(c) { |
| 260 | + var x = c["x"]; |
| 261 | + var y = c["y"]; |
| 262 | + var z = c["z"]; |
| 263 | +} |
| 264 | + |
| 265 | + |
| 266 | +//// [keyofAndIndexedAccess.d.ts] |
| 267 | +declare class Shape { |
| 268 | + name: string; |
| 269 | + width: number; |
| 270 | + height: number; |
| 271 | + visible: boolean; |
| 272 | +} |
| 273 | +declare class Item { |
| 274 | + name: string; |
| 275 | + price: number; |
| 276 | +} |
| 277 | +declare class Options { |
| 278 | + visible: "yes" | "no"; |
| 279 | +} |
| 280 | +declare type Dictionary<T> = { |
| 281 | + [x: string]: T; |
| 282 | +}; |
| 283 | +declare const enum E { |
| 284 | + A = 0, |
| 285 | + B = 1, |
| 286 | + C = 2, |
| 287 | +} |
| 288 | +declare type K00 = keyof any; |
| 289 | +declare type K01 = keyof string; |
| 290 | +declare type K02 = keyof number; |
| 291 | +declare type K03 = keyof boolean; |
| 292 | +declare type K04 = keyof void; |
| 293 | +declare type K05 = keyof undefined; |
| 294 | +declare type K06 = keyof null; |
| 295 | +declare type K07 = keyof never; |
| 296 | +declare type K10 = keyof Shape; |
| 297 | +declare type K11 = keyof Shape[]; |
| 298 | +declare type K12 = keyof Dictionary<Shape>; |
| 299 | +declare type K13 = keyof {}; |
| 300 | +declare type K14 = keyof Object; |
| 301 | +declare type K15 = keyof E; |
| 302 | +declare type K16 = keyof [string, number]; |
| 303 | +declare type K17 = keyof (Shape | Item); |
| 304 | +declare type K18 = keyof (Shape & Item); |
| 305 | +declare type KeyOf<T> = keyof T; |
| 306 | +declare type K20 = KeyOf<Shape>; |
| 307 | +declare type K21 = KeyOf<Dictionary<Shape>>; |
| 308 | +declare type NAME = "name"; |
| 309 | +declare type WIDTH_OR_HEIGHT = "width" | "height"; |
| 310 | +declare type Q10 = Shape["name"]; |
| 311 | +declare type Q11 = Shape["width" | "height"]; |
| 312 | +declare type Q12 = Shape["name" | "visible"]; |
| 313 | +declare type Q20 = Shape[NAME]; |
| 314 | +declare type Q21 = Shape[WIDTH_OR_HEIGHT]; |
| 315 | +declare type Q30 = [string, number][0]; |
| 316 | +declare type Q31 = [string, number][1]; |
| 317 | +declare type Q32 = [string, number][2]; |
| 318 | +declare type Q33 = [string, number][E.A]; |
| 319 | +declare type Q34 = [string, number][E.B]; |
| 320 | +declare type Q35 = [string, number][E.C]; |
| 321 | +declare type Q36 = [string, number]["0"]; |
| 322 | +declare type Q37 = [string, number]["1"]; |
| 323 | +declare type Q40 = (Shape | Options)["visible"]; |
| 324 | +declare type Q41 = (Shape & Options)["visible"]; |
| 325 | +declare type Q50 = Dictionary<Shape>["howdy"]; |
| 326 | +declare type Q51 = Dictionary<Shape>[123]; |
| 327 | +declare type Q52 = Dictionary<Shape>[E.B]; |
| 328 | +declare let cond: boolean; |
| 329 | +declare function getProperty<T, K extends keyof T>(obj: T, key: K): T[K]; |
| 330 | +declare function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]): void; |
| 331 | +declare function f10(shape: Shape): void; |
| 332 | +declare function f11(a: Shape[]): void; |
| 333 | +declare function f12(t: [Shape, boolean]): void; |
| 334 | +declare function f13(foo: any, bar: any): void; |
| 335 | +declare class Component<PropType> { |
| 336 | + props: PropType; |
| 337 | + getProperty<K extends keyof PropType>(key: K): PropType[K]; |
| 338 | + setProperty<K extends keyof PropType>(key: K, value: PropType[K]): void; |
| 339 | +} |
| 340 | +declare function f20(component: Component<Shape>): void; |
| 341 | +declare function pluck<T, K extends keyof T>(array: T[], key: K): T[K][]; |
| 342 | +declare function f30(shapes: Shape[]): void; |
| 343 | +declare function f31<K extends keyof Shape>(key: K): Shape[K]; |
| 344 | +declare function f32<K extends "width" | "height">(key: K): Shape[K]; |
| 345 | +declare class C { |
| 346 | + x: string; |
| 347 | + protected y: string; |
| 348 | + private z; |
| 349 | +} |
| 350 | +declare function f40(c: C): void; |
0 commit comments