Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript: Infer params from path #211

Merged
merged 9 commits into from Sep 28, 2021

Conversation

itsMapleLeaf
Copy link
Contributor

Closes #210

This will probably be a breaking change for TS users who manually typed their path params, I'm not sure if that warrants a major 馃 Open to alternative approaches as well.

types/index.d.ts Show resolved Hide resolved
Copy link
Contributor

@cbbfcd cbbfcd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

types/index.d.ts Outdated
Comment on lines 54 to 57
export interface RouteProps<RoutePath extends Path = Path> {
children?: ((params: ExtractRouteParams<RoutePath>) => ReactNode) | ReactNode;
path?: RoutePath;
component?: ComponentType<RouteComponentProps<ExtractRouteParams<RoutePath>>>;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering if there is any way to keep the backward compatibility for users who want to manually type their params, like:

Route<CustomParams> // params is of type `CustomParams`
Route // the type of params is inferred from path

Maybe we could move RoutePath to the second type argument and provide a default first argument like so:

export function Route<T extends DefaultParams = null, RoutePath extends Path = Path>(

But I have a little experience, so not sure if this will work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Owner

@molefrog molefrog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way to make the same trick for for the useRoute hook:

const [match, params] = useRoute("/app/:user") // params has the right type

@graphman65
Copy link
Contributor

Hi, I created another PR (not sure how to handle such cases as it's based on the commits of this one): #217 that contains the changes that you mentioned in the comments (backward compatibility and useRoute params type inference).

@itsMapleLeaf Feel free to copy the commit and include/cherry-pick it in your PR, you did most of the work, don't want to take credit for it.

@itsMapleLeaf
Copy link
Contributor Author

Hi, I created another PR (not sure how to handle such cases as it's based on the commits of this one): #217 that contains the changes that you mentioned in the comments (backward compatibility and useRoute params type inference).

@itsMapleLeaf Feel free to copy the commit and include/cherry-pick it in your PR, you did most of the work, don't want to take credit for it.

Thanks for that, I didn't have the time to come back to this 馃槄 Went ahead and cherry-picked it

types/index.d.ts Outdated Show resolved Hide resolved
@graphman65
Copy link
Contributor

@itsMapleLeaf Tested it and it works fine!

Let's add this test case and we should be good to go.

diff --git a/types/type-specs.tsx b/types/type-specs.tsx
index 81dae1e..2e2dd1e 100644
--- a/types/type-specs.tsx
+++ b/types/type-specs.tsx
@@ -90,7 +90,13 @@ const invalidParamsWithGeneric: Params<{ id: number }> = { id: 13 }; // $ExpectE
 
 // for pathToRegexp matcher
 <Route path="/:user([a-z]i+)/profile/:tab/:first+/:second*">
-  {({ user, tab, first, second }) => `${user}, ${tab}, ${first}, ${second}`}
+  {({ user, tab, first, second }) => {
+    user; // $ExpectType string
+    tab; // $ExpectType string
+    first; // $ExpectType string
+    second; // $ExpectType string | undefined
+    return `${user}, ${tab}, ${first}, ${second}`;
+  }}
 </Route>;
 
 /*

@itsMapleLeaf
Copy link
Contributor Author

@graphman65 Done 馃憤

For future reference, reviews have a "suggestion" feature, which makes it a lot easier to suggest changes, where I can add them in with a button click

types/type-specs.tsx Outdated Show resolved Hide resolved
Co-authored-by: S茅bastien Lacoste <graphman65@gmail.com>
types/index.d.ts Outdated
Comment on lines 54 to 57
export interface RouteProps<RoutePath extends Path = Path> {
children?: ((params: ExtractRouteParams<RoutePath>) => ReactNode) | ReactNode;
path?: RoutePath;
component?: ComponentType<RouteComponentProps<ExtractRouteParams<RoutePath>>>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Owner

@molefrog molefrog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @itsMapleLeaf @graphman65 !

@codecov
Copy link

codecov bot commented Sep 28, 2021

Codecov Report

Merging #211 (c9c2997) into master (fed3426) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##            master      #211   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            7         7           
  Lines          250       250           
  Branches        50        50           
=========================================
  Hits           250       250           
Impacted Files Coverage 螖
test/test-utils.js 100.00% <100.00%> (酶)

Continue to review full report at Codecov.

Legend - Click here to learn more
螖 = absolute <relative> (impact), 酶 = not affected, ? = missing data
Powered by Codecov. Last update fed3426...c9c2997. Read the comment docs.

@molefrog molefrog merged commit 29b109b into molefrog:master Sep 28, 2021
@molefrog
Copy link
Owner

Just released this change as an alpha version 2.8.0-alpha.1, could you check if the types are working?

Tried making a simple sandbox, but it doesn't seem to be working, https://codesandbox.io/s/little-fire-7bi1w?file=/src/App.tsx:410-415

@graphman65
Copy link
Contributor

I just created a sample project using 2.8.0-alpha.1 and it's working fine using typescript@4.4.2
The vscode client in codesanbox (used by the language server and linting) is using 4.1.2 so it should be working too.
I will investigate.

@graphman65
Copy link
Contributor

Ok so I investigated and this is an issue in codesanbox, not wouter.

The page is trying to load this file: https://prod-packager-packages.codesandbox.io/v1/typings/wouter/2.8.0-alpha.1.json but it fails with a 502 error.

But when I set the version of wouter to 2.7.4 it's working just fine and loading this file successfully. Looks like they are caching type info and it's not yet available for the new release.

I found a lot of issues mentioning this error and looks like it got fixed at some point but some users started to face the issue again 5 days ago. (codesandbox/codesandbox-client#5502).

@molefrog
Copy link
Owner

molefrog commented Oct 4, 2021

One thing I've realised is that we still need proper types for the Preact version, which is distributed as a separate npm package wouter-preact. The types for Preact are identical expect for the index.d.ts (see types/preact folder). Since ExtractRouteParams type is going to be probably identical to React's version, I think it makes sense to extract these utility types into a standalone type definition file, like types/route-params.d.ts for example. Let me know if you guys would like to work on that feature as this is something we will need for the upcoming release, otherwise I can start digging.

P.S. Seems like supporting type definitions is becoming a bit PITA, so I'm really thinking about converting the source code into TypeScript in v3 of the library 馃

@itsMapleLeaf itsMapleLeaf deleted the ts-infer-params-from-path branch October 4, 2021 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TypeScript: Infer params from path
4 participants