{"action":"created","issue":{"url":"https://api.github.com/repos/pelotom/unionize/issues/28","repository_url":"https://api.github.com/repos/pelotom/unionize","labels_url":"https://api.github.com/repos/pelotom/unionize/issues/28/labels{/name}","comments_url":"https://api.github.com/repos/pelotom/unionize/issues/28/comments","events_url":"https://api.github.com/repos/pelotom/unionize/issues/28/events","html_url":"https://github.com/pelotom/unionize/issues/28","id":314276923,"number":28,"title":"Proposal: restore old API of creating union via type parameter","user":{"login":"pelotom","id":128019,"avatar_url":"https://avatars2.githubusercontent.com/u/128019?v=4","gravatar_id":"","url":"https://api.github.com/users/pelotom","html_url":"https://github.com/pelotom","followers_url":"https://api.github.com/users/pelotom/followers","following_url":"https://api.github.com/users/pelotom/following{/other_user}","gists_url":"https://api.github.com/users/pelotom/gists{/gist_id}","starred_url":"https://api.github.com/users/pelotom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pelotom/subscriptions","organizations_url":"https://api.github.com/users/pelotom/orgs","repos_url":"https://api.github.com/users/pelotom/repos","events_url":"https://api.github.com/users/pelotom/events{/privacy}","received_events_url":"https://api.github.com/users/pelotom/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":9,"created_at":"2018-04-13T23:28:32Z","updated_at":"2018-04-17T18:40:36Z","closed_at":null,"author_association":"OWNER","body":"While we're making breaking changes for 2.0, I've been thinking about ways we could return to the simpler original API of Unionize. It used to be that the `unionize` function used a type parameter instead of an actual object to specify the mapping of tags to values:\r\n\r\n```ts\r\nconst Action = unionize<{\r\n  ADD_TODO: { id: string; text: string }\r\n  SET_VISIBILITY_FILTER: 'SHOW_ALL' | 'SHOW_ACTIVE' | 'SHOW_COMPLETED'\r\n  TOGGLE_TODO: { id: string }\r\n}>('type', 'payload')\r\n```\r\n\r\nSimple and clean!\r\n\r\nThe magic that powered this was ES6 `Proxy`s; unfortunately [it was pointed out](https://github.com/pelotom/unionize/issues/3) that proxies carried an enormous performance penalty, and thus we ended up with the current API involving `ofType` with its impossible signature of `<A>() => A`. It works and is efficient, but it's unsightly and unsafe.\r\n\r\nHow could we get back to something like what we had originally, but without using `Proxy`? Well, we only needed it to trap property accesses in support of the creation, `is` and `as` functions:\r\n\r\n```ts\r\nAction.ADD_TODO({ id: 'abc', text: 'hello world' });\r\nAction.is.ADD_TODO(obj);\r\nAction.as.ADD_TODO(obj);\r\n```\r\n\r\nBut we could alternatively make these functions which take a tag argument:\r\n\r\n```ts\r\nAction.create('ADD_TODO', { id: 'abc', text: 'hello world' });\r\nAction.is('ADD_TODO', obj);\r\nAction.as('ADD_TODO', obj);\r\n```\r\n\r\nThere could be curried versions of these as well, so that\r\n\r\n```ts\r\nAction.create('ADD_TODO'); // returns a creation function\r\nAction.is('ADD_TODO'); // returns a type guard\r\nAction.as('ADD_TODO'); // returns a casting function\r\n```\r\n\r\n_Slightly_ more verbose, but not much. The more I think about it, the more this tradeoff seems worth it to leave `ofType` behind.\r\n"},"comment":{"url":"https://api.github.com/repos/pelotom/unionize/issues/comments/382098709","html_url":"https://github.com/pelotom/unionize/issues/28#issuecomment-382098709","issue_url":"https://api.github.com/repos/pelotom/unionize/issues/28","id":382098709,"user":{"login":"twop","id":6633216,"avatar_url":"https://avatars1.githubusercontent.com/u/6633216?v=4","gravatar_id":"","url":"https://api.github.com/users/twop","html_url":"https://github.com/twop","followers_url":"https://api.github.com/users/twop/followers","following_url":"https://api.github.com/users/twop/following{/other_user}","gists_url":"https://api.github.com/users/twop/gists{/gist_id}","starred_url":"https://api.github.com/users/twop/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/twop/subscriptions","organizations_url":"https://api.github.com/users/twop/orgs","repos_url":"https://api.github.com/users/twop/repos","events_url":"https://api.github.com/users/twop/events{/privacy}","received_events_url":"https://api.github.com/users/twop/received_events","type":"User","site_admin":false},"created_at":"2018-04-17T18:40:36Z","updated_at":"2018-04-17T18:40:36Z","author_association":"CONTRIBUTOR","body":"I guess it makes sense to provide a draft impl for proxy. \r\n```ts\r\nconst creatorsProxy = {\r\n  // note you can even momoize it.\r\n  get: (union, tag) => (payload)=> ({\r\n    union.create(tag, payload)\r\n  })\r\n};\r\n\r\nconst unionObj = {...} // result of unionize\r\n\r\n// add creators\r\nunionObj.creators = new Proxy(unionObj, creatorsProxy);\r\n```\r\n\r\nSo you pay the price for `Proxy` only once when you destructure `creators`. So usually once per file or even less.\r\n\r\nThat being said, I think `ofType<void>()` is good enough. But it worth pointing out the the original api had a clearer declaration semantics :) Also `Proxy` cost is virtually nonexistent."}}
{"actor":{"display_login":"twop"}}