/* @flow */

function testKeysOfObject(str: string, lit: 'hi') {
  (str: $Keys<Object>); // Any string should be fine
  if (str) {
    (str: $Keys<Object>); // No error, truthy string should be fine
  }
  ('hi': $Keys<Object>); // String literal should be fine

  (123: $Keys<Object>); // Error: number -> keys of Object
}

type StrDict = {[key: string]: mixed};
function testKeysOfStrDict(str: string, lit: 'hi') {
  (str: $Keys<StrDict>); // Any string should be fine
  if (str) {
    (str: $Keys<StrDict>); // No error, truthy string should be fine
  }
  ('hi': $Keys<StrDict>); // String literal should be fine

  (123: $Keys<StrDict>); // Error: number -> keys of StrDict
}

type StrLitDict = {[key: 'hi']: mixed};
function testKeysOfStrLitDict(str: string, lit: 'hi') {
  (str: $Keys<StrLitDict>); // Error: Not all strings are allowed
  if (str) {
    (str: $Keys<StrLitDict>); // Error: Not all truthy strings are allowed
  }
  ('hi': $Keys<StrLitDict>); // The right string literal is allowed
  ('bye': $Keys<StrLitDict>); // Error: The wrong string literal is not allowed

  (123: $Keys<StrLitDict>); // Error: number -> keys of StrLitDict
}

type ObjLit = {hi: mixed};
function testKeysOfOtherObj(str: string, lit: 'hi') {
  (str: $Keys<ObjLit>); // Error: string -> keys of ObjLit
  if (str) {
    (str: $Keys<ObjLit>); // Error: truthy string -> keys of ObjLit
  }
  ('hi': $Keys<ObjLit>); // String literal should be fine

  (123: $Keys<ObjLit>); // Error: number -> keys of ObjLit
}
