declare const mixed: unknown;
declare const any: any;
declare const myObject: any;
declare const myFunction: any;

declare const inexactObject: { x: string };
declare const exactObject: { x: string };

declare const unionOfObjects: { x: string } | { y: string };
declare const intersectionOfObjects: { x: string } & { y: string };

class myClass {}
declare const instance: myClass;

// We disallow accessing properties on mixed
if (mixed.thisPropDoesNotExist) {} // Error
// But we allow accessing properties on truthy or non-maybe mixed
if (mixed && mixed.thisPropDoesNotExist) {} // No error
if (mixed != null && mixed.thisPropDoesNotExist) {} // No error

// We allow accessing properties on the any types
if (any.thisPropDoesNotExist) {} // No error
if (myObject.thisPropDoesNotExist) {} // No error
if (myFunction.thisPropDoesNotExist) {} // No error

// We disallow testing unknown properties on inexact objects
if (inexactObject.thisPropDoesNotExist) {} // Error

// We disallow testing unknown properties on exact objects
if (exactObject.thisPropDoesNotExist) {} // Error

// We disallow testing unknown properties on unions
if (unionOfObjects.thisPropDoesNotExist) {} // Error
// But we allow testing properties which appear on at least one branch
if (unionOfObjects.y) {} // No error

// We disallow testing unknown properties on intersections
if (intersectionOfObjects.thisPropDoesNotExist) {} // Error
// But we allow testing properties which appear on at least one branch
if (intersectionOfObjects.y) {} // No error

// We disallow accessing unknown properties on class statics
if (myClass.thisPropDoesNotExist) {} // Error
// and on class instances
if (instance.thisPropDoesNotExist) {} // Error
