New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add typescript types #24
Conversation
@kingdaro I kind of coded up a possible augmentation we could do to react without injecting the matching props into every component: https://gist.github.com/joshthecoder/88f2be7428e7c9b3fb8840ce16ff1d96 I explained this on the other issue but to summarize again we are defining new createElement types instead that match to only components that have props which extend from our route component props. I haven't tested this at all yet so not 100% sure if this is viable yet. |
Should we also include some test files to verify the d.ts file is correct? We could follow the same structure used by https://github.com/DefinitelyTyped/DefinitelyTyped. Maybe place the files in a "types" folder. We would need to add |
I have a test bed project, and I'm not able to get this working correctly. I might be doing something incorrectly on my end, so try it out on your end instead to see if you can get it working.
Good idea 👍 @ryanflorence Comments on folder structure? Specifically, where |
@kingdaro yeah doesn't seem to be working for me complains that path isn't an allowed prop when I try to set it on a route component :| I'm thinking maybe we just mix in these props with RouteComponentRouteProps (I'm actually thinking we just call this RouteComponentProps?). Those are actual props even if you shouldn't really need to use them. Not sure there is too much harm. I'll fiddle around a bit more and see if I can get it working. |
@kingdaro
Put stuff related to each other by each other. Just like But really I don't care, wherever you'd put it is fine. |
Here's what I settled on for typing the route component props: export type RouteComponentProps<TParams = {}> = Partial<TParams> & {
path: string;
default?: boolean;
location?: WindowLocation;
navigate?: NavigateFn;
uri?: string;
}; import * as React from "react";
import { render } from "react-dom";
import { RouteComponentProps, Router } from "../";
type DashParams = { id: string };
let Home = (props: RouteComponentProps) => <div>Home</div>;
let Dash = (props: RouteComponentProps<DashParams>) => (
<div>Dash for item ${props.!id}</div>
);
render(
<Router>
<Home path="/" />
<Dash path="/dashboard/:id" />
</Router>,
document.getElementById("app-root")
); I merged them all into one props interface, as suggested before, and I made all of its receiving props optional so they don't need to be provided when using them in Not completely ideal, since either undefined checks or a null assertion
With that in mind, this is probably good enough, just so we can get some types out there and make refinements later if needed. |
e856231
to
8503197
Compare
8503197
to
f9d9724
Compare
@kingdaro Looking good. I'll give this a test run and report back if I run into any issues. Nice work |
I tried to enforce this invariant, but couldn't get it working. Maybe you guys could take a stab at it? |
also split up the external and internal props for readability
@antmdvs I was able to enforce either Though I recall the react-transition-group package doing something like that, the error messages I've gotten from using it are a little cryptic, and I don't think it would be worth it. |
@kingdaro It looks like your last change breaks IntelliSense, though. The Anyway, to clarify what I meant, I was trying to do something like this in the
|
I attempted to do it the way the linked answer does (with extending interfaces), but the props still don't show up on autocomplete. As far as I can tell, it's no different than what I'd done already. If preserving autocomplete is a priority, then making That sounds like a fine solution to me, though. Reach Router will still error at runtime if one forgets to define a
Right, and that unfortunately doesn't work, because JSX elements lose their typing information in usage. Elements collapse to |
Tough one.. FWIW, I'd personally favor having them in the autocomplete list and letting the runtime error handle the validation. I use autocomplete heavily when exploring a new API and it would seem wrong if a component accepted props (without TypeScript complaining) that don't appear in the autocomplete list.
Weird. I just find that super confusing because of this and this. Oh well. |
Yeah, I rely on autocomplete pretty heavily myself, and I imagine it's not too different for the rest of the TS ecosystem. I'll opt for the optional props then. |
I copied your definition file to run it locally until this module is ready. One thing I had to change was your LinkProps so it accepts Additionally I omitted the href prop because it will be ignored, so I'd rather TS give a warning about using href. Here's my code:
Thanks for the work on the definitions 👍 |
Thanks for the patch, I'll go ahead and throw that in |
I just have a question. |
I'm not 100% sure on that myself, but I imagine a peer dependency wouldn't be the best idea, as it would show a warning for everyone who installs the library to install TS, including those who don't use TS. Good to point that out, though. It seemed reasonable to rely on people having their TS version updated, but that might not always be the case, and an error on Maybe a simple That, or we could remove the usage of A few options here. Leaning towards the upgrade comment. |
So things brings up another Q: If reach router shipped a @types package instead of a bundled index.d.ts, non-TS users wouldn't be affected. Do you think that would be preferable? |
Another thing to consider is that if reach router bundles index.d.ts, those definitions need to be always kept up to date. Otherwise it's quite inconvenient for consumers to add their own definitions after a breaking change. With @ types, it would be easier to include some (albeit suboptimal) type definitions via I faced this problem recently with redux-thunk (see reduxjs/redux-thunk#169). I think it's also why the ts docs recommend using @ types for non-ts packages. |
Hm... all things considered, hitting up DefinitelyTyped is starting to sound like the better option. I guess it wouldn't be too much trouble to move the typedefs over there. I'll probably get around to that this evening, then. Closing for now |
Fixes #11
As I mentioned in another issue, one thing I'm not sure about is how to handle the
path
property on route components. Here's a usage example of what I came up with:Someone also suggested module augmentation as an alternative, though that would mean allowing the
path
property to appear on any component in the entire app, however it would certainly look cleaner in usage.Comments on how to best handle this (and on other general corrections) are welcome.