Preserve generics when using observer#244
Conversation
|
@xaviergonz @mweststrate Could really use your help with reviewing this, I am not that strong with TypeScript yet. |
|
I'll try to take a look tomorrow.
…On Mon, Nov 25, 2019 at 9:22 AM Daniel K. ***@***.***> wrote:
@xaviergonz <https://github.com/xaviergonz> @mweststrate
<https://github.com/mweststrate> Could really use your help with
reviewing this, I am not that strong with TypeScript yet.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#244?email_source=notifications&email_token=AAN4NBF57HLDORTIEXOH4M3QVOKNFA5CNFSM4JRFGI42YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEFBWLTY#issuecomment-558065103>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAN4NBCLM6NSDEZXI6TFME3QVOKNFANCNFSM4JRFGI4Q>
.
|
|
I have noticed an issue where empty options were not accepted, which while silly could be an issue in future if more options are added. Should be fixed in last commit. |
|
The types are getting fairly complicated / overloaded now, I wonder if we can make it a bit simpler by avoiding overloads, and inferring return type roughly as follows, I think the type inference and error messages will be better if we do it this way, as it avoids 'backtracking' the generic arguments, and takes the input argument as starting point: export function observer<
T extends React.FunctionComponent<any> | React.RefForwardingComponent<any>,
Options extends IObserverOptions
>(
baseComponent: C,
options?: Options,
): Options extends { forwardRef: true }
? C extends React.RefForwardingComponent<infer TRef, infer P>
? React.ForwardRefExoticComponent<React.PropsWithoutRef<P> & React.RefAttributes<TRef>>
: never /* forwardRef set for a non forwarding component */
: C |
|
As Michel said...
@Kukkimonsuta Did you try to remove other overloads? |
|
I have merged the two new overloads using Michels sample with slight modifications, however I'm not certain whether we want to remove the original overloads too as it would be breaking change and following transformation in users code would have to be done by users during migration to new version: interface IProps {
value: string;
}
const TestComponent = observer<IProps>(({ value, children }) => {
return null
})to interface IProps {
value: string;
}
const TestComponent = observer(({ value, children }: React.PropsWithChildren<IProps>) => {
return null
}) |
|
Hmmm, I've never seen the first pattern in the wild, personally. I think
the typical thing to do is to add `children: React.ReactNode` to the
`IProps`, especially because they don't have to be necessarily react nodes.
Personally I'd release it as minor, and rollback or add the additional
overload if it is an obstacle for many.
…On Wed, Dec 18, 2019 at 5:14 PM Lukáš Novotný ***@***.***> wrote:
I have merged the two new overloads using Michels sample with slight
modifications, however I'm not certain whether we want to remove the
original overloads too as it would be breaking change and following
transformation in users code would have to be done by users during
migration to new version:
interface IProps {
value: string;
}const TestComponent = observer<IProps>(({ value, children }) => {
return null
})
to
interface IProps {
value: string;
}const TestComponent = observer(({ value, children }: React.PropsWithChildren<IProps>) => {
return null
})
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#244?email_source=notifications&email_token=AAN4NBB6AO2YGXXGRMDB6STQZJK65A5CNFSM4JRFGI42YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHG2U6I#issuecomment-567126649>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAN4NBDK4GRUBDOTHKUEXS3QZJK65ANCNFSM4JRFGI4Q>
.
|
|
Btw, this |
|
I am usually doing this and we have various aliases for children ( type TProps = SomeChildren & {
extra: string
}
export const Comp = observer<TProps>(({ extra }) => { ... })I suppose doing The "problem" with official |
|
ok, maybe this pattern is more common than anticipated, and we should
continue support it, if 2/3 of the people in this thread already use it
:-P. It's pretty as well. I don't think we have it somewhere documented
explicitly, don't we?
…On Wed, Dec 18, 2019 at 7:33 PM Daniel K. ***@***.***> wrote:
I am usually doing this and we have various aliases for children (
NoChildren, SingleChild, Required<SomeChildren>, etc...).
type TProps = SomeChildren & {
extra: string
}
export const Comp = observer<TProps>(({ extra }) => { ... })
I suppose doing observer(({ extra }: TProps) => { ... }) is not too
horrible, but it will be pain to refactor that. We should probably create a
codemod <https://github.com/tusharmath/ts-codemod> or something to
migrate this automatically.
The "problem" with official PropsWithChildren is it refers to ReactNode
which includes undefined and that is wrong (an app will crash). It's some
legacy crap going deep into how class components work. I have a custom
ReactNode as using only FC and it works nicely.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#244?email_source=notifications&email_token=AAN4NBDXPECZXFNGQH77UYLQZJ3GZA5CNFSM4JRFGI42YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHHHERI#issuecomment-567177797>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAN4NBFXDLWMRT3R4EPGU5LQZJ3GZANCNFSM4JRFGI4Q>
.
|
|
It actually is documented ... https://mobx-react.js.org/observer-hoc |
|
Hahaha cool!
…On Wed, Dec 18, 2019 at 8:01 PM Daniel K. ***@***.***> wrote:
It actually is documented ... https://mobx-react.js.org/observer-hoc
No surprise there since I wrote that docs 😎
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#244?email_source=notifications&email_token=AAN4NBFGGWQ2YXFWAHAUDZ3QZJ6SHA5CNFSM4JRFGI42YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHHKDZQ#issuecomment-567189990>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAN4NBESKUMTG22I4NV5WETQZJ6SHANCNFSM4JRFGI4Q>
.
|
|
I've experimented a bit further with this, however at this point I think it's out of my ability to merge rest of the overloads into one declaration. The main issue I see is that there is a conflict of typing authority between the two: |
|
Sorry for the late follow up! Completely dropped the ball here, but I think it is fine as it is! |
|
Ok, since this is going to |
* Schedule uncommitted reaction cleanup (#121) * Test cleaning up reactions for uncommitted components * First attempt at a fix for cleaning up reactions from uncommitted components * Use debounce instead of fixed interval * Add unit test for missing observable changes before useEffect runs This is a test to check that observable changes made between the first component render and commit are not lost. It currently fails (and did so before the change in PR #119) * Add test for cleanup timer firing too early for some components This demonstrates (in a slightly contrived way) how, if the cleanup timer fires between a recent component being rendered and it being committed, that it would incorrectly tidy up a reaction for a soon-to-be-committed component. * Update test for missing changes to check Strict and non-Strict mode We had an existing test to check that observable changes between render and commit didn't go missing, but it only checked in Strict mode, and there's a problem with non-Strict mode. * Add cleanup tracking and more tests This adds full cleanup tracking, and even more tests: - we now track how long ago potentially leaked reactions were created, and only clean those that were leaked 'a while ago' - if a reaction is incorrectly disposed because a component went away for a very long time and came back again later (in a way React doesn't even do right now), we safely recreate it and re-render - trap the situation where a change is made to a tracked observable between first render and commit (where we couldn't force an update because we hadn't _been_ committed) and force a re-render - more unit tests * Fix renamed test file When I renamed this file, I forgot the .test. suffix. D'oh. * Extract tracking and cleanup logic out to separate file * Update src/useObserver.ts Co-Authored-By: RoystonS <royston@shufflebotham.org> * Move some more tracking internals into the tracking code * 2.0.0-alpha.0 * 2.0.0-alpha.1 * 2.0.0-alpha.2 * Upgrade to React 16.9 * Add dedup script and run it * Remove deprecated hooks * Increase size limit * Remove note about Next version * Remove unused productionMode util * Improve readme * Pin dependencies * Merge master properly * Ignore build cache files * Revert removal of tsdx dep * Remove .browserlistrc * 2.0.0-alpha.3 * Bundling need to use build tsconfig * 2.0.0-alpha.4 * Remove object destructuring from optimizeForReactDOM/Native (#240) * Preserve generics when using `observer` (#244) * Preserve generics when using `observer` * Remove any casting from statics as it's no longer needed * Re-add overloads for explicitly specifying props type * Allow for passing options without `forwardRef` * Merge new `observer` overloads * Remove copy of UMD bundle * 2.0.0-alpha.5 * Batched updates are mandatory * Replace .npmignore with files field * Fix tests * Increase size limit Co-authored-by: Royston Shufflebotham <royston@shufflebotham.org> Co-authored-by: Renovate Bot <bot@renovateapp.com> Co-authored-by: Tarvo R <TarvoReinpalu@gmail.com> Co-authored-by: Lukáš Novotný <lukas@dramiel.com>
Related issue #243
This change allows wrapping generic components while preserving generic parameters.
There is also unintended change that preserves all static types. This has mostly positive effect, though
$$typeof,type,compare, andrender(which are not copied over) remain with their original type if defined on base component. I didn't find a way to omit these properties as any kind of narrowing will cause generic parameters to be converted tounknown.