{"action":"created","issue":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/12793","repository_url":"https://api.github.com/repos/Microsoft/TypeScript","labels_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/12793/labels{/name}","comments_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/12793/comments","events_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/12793/events","html_url":"https://github.com/Microsoft/TypeScript/issues/12793","id":194580098,"number":12793,"title":"Partial does not solve React.setState","user":{"login":"AlexGalays","id":1375586,"avatar_url":"https://avatars.githubusercontent.com/u/1375586?v=3","gravatar_id":"","url":"https://api.github.com/users/AlexGalays","html_url":"https://github.com/AlexGalays","followers_url":"https://api.github.com/users/AlexGalays/followers","following_url":"https://api.github.com/users/AlexGalays/following{/other_user}","gists_url":"https://api.github.com/users/AlexGalays/gists{/gist_id}","starred_url":"https://api.github.com/users/AlexGalays/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AlexGalays/subscriptions","organizations_url":"https://api.github.com/users/AlexGalays/orgs","repos_url":"https://api.github.com/users/AlexGalays/repos","events_url":"https://api.github.com/users/AlexGalays/events{/privacy}","received_events_url":"https://api.github.com/users/AlexGalays/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2016-12-09T12:00:57Z","updated_at":"2016-12-09T16:24:58Z","closed_at":null,"body":"Traditionally in TS, the absence of value or an explicit undefined value was exactly the same thing.\r\nPerhaps it still even makes sense for Partial, but I thought Partial was meant to solve the React setState problem; and I believe it's still not solved today.\r\n\r\n**TypeScript Version:**  2.1.4\r\n\r\n**Code**\r\n\r\n```ts\r\ntype State = { veryImportant: number }\r\n\r\n// This compiles fine with all the mandatory flags (strictNullChecks, etc)\r\n// if setState uses Partial<State>\r\n// This is a huge invariant violation and can happen very easily for instance\r\n// by setting `veryImportant` to a nullable variable.\r\nthis.setState({ veryImportant: undefined })\r\n```\r\n\r\n**Expected behavior:**\r\nA non nullable property should not be updatable with null/undefined with strictNullChecks.\r\n\r\nWe need to be able to say \"give me an object that\r\n1) Either do not declare a property I have\r\n2) Or if it does, must have the same exact type (not nullable)\r\n\r\nBy the way, I don't even use React, but this is a fairly common and useful behavior to have.\r\n"},"comment":{"url":"https://api.github.com/repos/Microsoft/TypeScript/issues/comments/266055843","html_url":"https://github.com/Microsoft/TypeScript/issues/12793#issuecomment-266055843","issue_url":"https://api.github.com/repos/Microsoft/TypeScript/issues/12793","id":266055843,"user":{"login":"ahejlsberg","id":4226954,"avatar_url":"https://avatars.githubusercontent.com/u/4226954?v=3","gravatar_id":"","url":"https://api.github.com/users/ahejlsberg","html_url":"https://github.com/ahejlsberg","followers_url":"https://api.github.com/users/ahejlsberg/followers","following_url":"https://api.github.com/users/ahejlsberg/following{/other_user}","gists_url":"https://api.github.com/users/ahejlsberg/gists{/gist_id}","starred_url":"https://api.github.com/users/ahejlsberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ahejlsberg/subscriptions","organizations_url":"https://api.github.com/users/ahejlsberg/orgs","repos_url":"https://api.github.com/users/ahejlsberg/repos","events_url":"https://api.github.com/users/ahejlsberg/events{/privacy}","received_events_url":"https://api.github.com/users/ahejlsberg/received_events","type":"User","site_admin":false},"created_at":"2016-12-09T16:24:58Z","updated_at":"2016-12-09T16:24:58Z","body":"I believe this is what you're looking for:\r\n\r\n```ts\r\nfunction setState<T, K extends keyof T>(obj: T, state: Pick<T, K>) {\r\n    for (let k in state) {\r\n        obj[k] = state[k];\r\n    }\r\n}\r\n\r\ninterface Foo {\r\n    a: string;\r\n    b: number;\r\n}\r\n\r\nlet foo: Foo = { a: \"hello\", b: 42 };\r\nsetState(foo, { a: \"test\", b: 43 })\r\nsetState(foo, { a: \"hi\" });\r\nsetState(foo, { b: 27 });\r\nsetState(foo, { });\r\nsetState(foo, { a: undefined });  // Error\r\nsetState(foo, { c: true });  // Error\r\n```"}}
{"actor":{"display_login":"ahejlsberg"}}