{"action":"opened","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/20363","repository_url":"https://api.github.com/repos/Microsoft/TypeScript","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/20363/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/20363/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/20363/events","html_url":"https://github.com/Microsoft/TypeScript/issues/20363","id":278074230,"number":20363,"title":"Bad types of `hasOwnProperty`","user":{"login":"nenadalm","id":1227933,"avatar_url":"https://avatars0.githubusercontent.com/u/1227933?v=4","gravatar_id":"","url":"https://api.github.com/users/nenadalm","html_url":"https://github.com/nenadalm","followers_url":"https://api.github.com/users/nenadalm/followers","following_url":"https://api.github.com/users/nenadalm/following{/other_user}","gists_url":"https://api.github.com/users/nenadalm/gists{/gist_id}","starred_url":"https://api.github.com/users/nenadalm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nenadalm/subscriptions","organizations_url":"https://api.github.com/users/nenadalm/orgs","repos_url":"https://api.github.com/users/nenadalm/repos","events_url":"https://api.github.com/users/nenadalm/events{/privacy}","received_events_url":"https://api.github.com/users/nenadalm/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2017-11-30T10:43:55Z","updated_at":"2017-11-30T10:43:55Z","closed_at":null,"author_association":"NONE","body":"Hi. `hasOwnProperty` has following type:\r\n\r\n```typescript\r\nhasOwnProperty(v: string): boolean;\r\n```\r\n\r\nwhich is not that useful for type system.\r\n\r\nI wanted to write more useful version, but it seems to be impossible to type. So far best I could come up with is:\r\n\r\n```typescript\r\nfunction hasProp<P extends string, O extends object>(prop: P, object: O): object is (O & Record<P, u.AnyValue>) {\r\n    return object.hasOwnProperty(prop);\r\n}\r\n\r\nfunction hasProp2<P extends string, O extends object>(prop: P, object: O): prop is keyof object {\r\n    return object.hasOwnProperty(prop);\r\n}\r\n\r\nfunction propIsDefined<P extends string, O extends object>(prop: P, object: O) {\r\n    if (!hasProp(prop, object)) {\r\n        throw new Error();\r\n    }\r\n\r\n    if (!hasProp('wtf', object)) {\r\n        throw new Error();\r\n    }\r\n\r\n    // following line shows error, even though the prop was checked before.\r\n    const val = object[prop];\r\n\r\n    // following line works - `val2` has type `u.AnyValue`\r\n    // so the function `hasProp` only works if `prop` argument is passed as string (not string variable)\r\n    const val2 = object.wtf;\r\n\r\n    if (!hasProp2(prop, object)) {\r\n        throw new Error();\r\n    }\r\n\r\n    // following line works, but type of `val3` is any, which is bad, because it means\r\n    // that typescript won't provide any level of type safety\r\n    // I wasn't able to type the function so that `val3` is of type `u.AnyType`\r\n    const val3 = object[prop];\r\n}\r\n```\r\n\r\ntype `u.AnyType` mentioned above is defined like so:\r\n```typescript\r\n// https://github.com/Microsoft/TypeScript/issues/6230#issuecomment-212755825\r\nexport interface AnyObject {\r\n    [key: string]: AnyValue;\r\n}\r\nexport interface AnyArray extends Array<AnyValue> {}\r\nexport type AnyValue =\r\n    string |\r\n    number |\r\n    boolean |\r\n    null |\r\n    undefined |\r\n    AnyArray |\r\n    AnyObject;\r\n```\r\npurpose of it is that I can work safely with values for which type is not known (as `any` allows me to do whtatever I want without checking anything)."}}
{"actor":{"display_login":"nenadalm"}}