1190 lines
33 KiB
TypeScript
1190 lines
33 KiB
TypeScript
//// [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;
|
|
}
|