-
Notifications
You must be signed in to change notification settings - Fork 30.5k
[express-serve-static-core] add RouteParameters type for IRouterMatcher that uses template literal types #51262
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
Conversation
|
👋 Hi there! I’ve run some quick measurements against master and your PR. These metrics should help the humans reviewing this PR gauge whether it might negatively affect compile times or editor responsiveness for users who install these typings. Let’s review the numbers, shall we? Comparison details 📊
It looks like nothing changed too much. I won’t post performance data again unless it gets worse. |
|
@DetachHead Thank you for submitting this PR! I see this is your first time submitting to DefinitelyTyped 👋 — I'm the local bot who will help you through the process of getting things through. This is a live comment which I will keep updated. 2 packages in this PR
Code ReviewsBecause this is a widely-used package, a DT maintainer will need to review it before it can be merged. You can test the changes in this PR in the Playground. Status
Once every item on this list is checked, I'll ask you for permission to merge and publish the changes. Diagnostic Information: What the bot saw about this PR{
"type": "info",
"now": "-",
"pr_number": 51262,
"author": "DetachHead",
"headCommitOid": "57ab75649a406b6c891ef9c27a22a348267bc668",
"lastPushDate": "2021-05-25T15:31:18.000Z",
"lastActivityDate": "2021-05-25T16:26:28.000Z",
"hasMergeConflict": false,
"isFirstContribution": true,
"tooManyFiles": false,
"popularityLevel": "Critical",
"pkgInfo": [
{
"name": "express-serve-static-core",
"kind": "edit",
"files": [
{
"path": "types/express-serve-static-core/express-serve-static-core-tests.ts",
"kind": "test"
},
{
"path": "types/express-serve-static-core/index.d.ts",
"kind": "definition"
},
{
"path": "types/express-serve-static-core/package.json",
"kind": "package-meta-ok"
},
{
"path": "types/express-serve-static-core/ts4.0/express-serve-static-core-tests.ts",
"kind": "test"
},
{
"path": "types/express-serve-static-core/ts4.0/index.d.ts",
"kind": "definition"
},
{
"path": "types/express-serve-static-core/ts4.0/tsconfig.json",
"kind": "package-meta-ok"
},
{
"path": "types/express-serve-static-core/ts4.0/tslint.json",
"kind": "package-meta",
"suspect": "not [the expected form](https://github.com/DefinitelyTyped/DefinitelyTyped#user-content-linter-tslintjson) (check: `rules`)"
}
],
"owners": [
"borisyankov",
"19majkel94",
"kacepe",
"micksatana",
"samijaber",
"JoseLion",
"dwrss",
"andoshin11"
],
"addedOwners": [],
"deletedOwners": [],
"popularityLevel": "Critical"
},
{
"name": "express",
"kind": "edit",
"files": [
{
"path": "types/express/express-tests.ts",
"kind": "test"
},
{
"path": "types/express/package.json",
"kind": "package-meta-ok"
},
{
"path": "types/express/ts4.0/express-tests.ts",
"kind": "test"
},
{
"path": "types/express/ts4.0/index.d.ts",
"kind": "definition"
},
{
"path": "types/express/ts4.0/tsconfig.json",
"kind": "package-meta-ok"
},
{
"path": "types/express/ts4.0/tslint.json",
"kind": "package-meta",
"suspect": "not [the expected form](https://github.com/DefinitelyTyped/DefinitelyTyped#user-content-linter-tslintjson) (check: `rules`)"
}
],
"owners": [
"borisyankov",
"CMUH",
"puneetar",
"dfrankland"
],
"addedOwners": [],
"deletedOwners": [],
"popularityLevel": "Critical"
}
],
"reviews": [
{
"type": "stale",
"reviewer": "danvk",
"date": "2021-05-25T14:25:23.000Z",
"abbrOid": "51f372c"
},
{
"type": "stale",
"reviewer": "robertvanhoesel",
"date": "2021-05-25T12:17:12.000Z",
"abbrOid": "59dc475"
},
{
"type": "stale",
"reviewer": "JoseLion",
"date": "2021-05-13T01:05:28.000Z",
"abbrOid": "59dc475"
}
],
"mainBotCommentID": 779863981,
"ciResult": "pass"
} |
|
🔔 @borisyankov @19majkel94 @kacepe @micksatana @samijaber @JoseLion @dwrss @andoshin11 @CMUH @puneetar @dfrankland — please review this PR in the next few days. Be sure to explicitly select |
|
@DetachHead The CI build failed! Please review the logs for more information. Once you've pushed the fixes, the build will automatically re-run. Thanks! |
|
Inspecting the JavaScript source for this package found some properties that are not in the .d.ts files. express (unpkg)was missing the following properties:
|
|
Welllll, this package is literally the main reason that template literal types exist, so I think we should merge this PR eventually. I'm going to merge it in about 16 hours, so that I have all day to watch for complaints. @DetachHead is that a good time for you? If not, I'll be prepared to revert the merge so you can fix any bugs at your leisure. |
|
I'll probably be asleep as that's around midnight for me. But I'll check first thing in the morning |
| }); | ||
|
|
||
| // Default types - not using RouteParameters | ||
| app.post('/' as string, (req, res) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a decent fallback workaround for non standard implementations. Would users still be able to provide custom parameters like in https://github.com/DefinitelyTyped/DefinitelyTyped/pull/51262/files#diff-c5d8f61506d81e402ccb7f5f031730ce5ee044b86777af13924d7edfae4243f1R45
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, this works:
app.get<{ foo: string; bar: number }>('/' as string, req => {
req.params.foo; // $ExpectType string
req.params.bar; // $ExpectType number
req.params.baz; // $ExpectError
});i can add a test for this if you'd like
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, good to have this workaround on hand for when it might break someones implementation (although it is hard to imagine how it would). This is a great PR!
danvk
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall very excited about this change! See comment about optional params in paths. I wouldn't want to block on that, but it would be worth seeing how hard it is to handle them correctly.
types/express-serve-static-core/ts4.0/express-serve-static-core-tests.ts
Outdated
Show resolved
Hide resolved
| res.locals.foo; // $ExpectType boolean | ||
| res.locals.bar; // $ExpectError | ||
| res.send({ foo: 'ok' }); // $ExpectType Response<any, { foo: boolean; }, number> | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Express docs have a few examples of tricky routes: https://expressjs.com/en/guide/routing.html#route-parameters
It would be a good idea to add them to the tests here to make sure they work as expected:
/flights/:from-:to/plantae/:genus.:species/user/:userId(\d+)
While it's not explicitly mentioned on that page, if you click through to path-to-regexp, it mentions that parameters can be optional, i.e. /path/:param? should make the type of req.params.param be string | undefined.
This may be tested elsewhere, but the path can also be a regular expression, and that should continue to work as before (there are no regex literals… yet!).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, wasn't aware of this. i'll add support for -, . and ?, though the regex will probably just have to be ignored
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about just adding a test for /path/:param? so that we know what the behavior is after this PR? Even if we know it's incorrect, it will be a good place to capture the context from this discussion and what more correct behavior would be in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done. though i'm keen to rewrite the RouteParameters type to support this as well as properly ignore regex wrapped in parentheses. i think it'll need to be more like a lexer instead of just splitting on '/'|'-'|'.'. i'll get on that tomorrow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
@danvk, @robertvanhoesel, @JoseLion Thank you for reviewing this PR! The author has pushed new commits since your last review. Could you take another look and submit a fresh review? |
|
@DetachHead The CI build failed! Please review the logs for more information. Once you've pushed the fixes, the build will automatically re-run. Thanks! |
|
@DetachHead you probably aren't still awake, but it looks like the PR is in a done state now, and the next chunk of work is a fairly large, separate thing. I'll merge this in a couple of hours in the off chance that you'll have a chance to object before then. |
|
Yep all good to merge. Heading off to bed now |
|
I just published |
|
I just published |
|
I think the way that these changes were set up still allows TS versions < 4.0 to get the d.ts files for the template literals which breaks their builds - #53397 |
|
For anybody having trouble right now with optional parameters and getting an error at build time: server.get('/download/:entity/:name?', async (req, res, next) => {
const entity = req.params.entity;
// used to work in the past prior this PR
const nameOr = req.params.name; // <<-- error here: Property 'name' does not exist on type 'RouteParameters<"/:entity/preview/:name?">'. Did you mean 'name?'?
// as suggested
const nameOr = req.params['name?']; // build will work, but variable will always be undefined
// ...
});The workaround that worked for me is changing the route to: // Workaround: add empty string: route + ''
server.get('/download/:entity/:name?' + '', async (req, res, next) => {
// ...
});So just by concatenating two strings as a route it seems that the work put in to this PR will get disabled. The type of |
|
you can do this: server.get<{entity: string, name?: string}>('/download/:entity/:name?', async (req, res, next) => {
// ...
});that way you still get the type safety and aren't adding any unnecessary runtime code. sorry about that, i'll try to get a PR ready with a fix for this within the next few days |
|
@DetachHead is it really intended that projects using typescript versions below 4 should receive the type definitions from the Currently ,in the package.json of both @types/express and @types/express-serve-static-core the "typesVersions": {
"<=4.0": { "*": ["ts4.0/*"] }
} |
|
@angelsvirkov that's intentional yeah. i followed the same pattern the rest of the repo seems to use. that's also how it's shown in the example here |
@types/express-serve-static-core requires typescript version >= 4.1, see DefinitelyTyped/DefinitelyTyped#51262
@types/express-serve-static-core requires typescript version >= 4.1, see DefinitelyTyped/DefinitelyTyped#51262

Please fill in this template.
npm test <package to test>.Select one of these and delete the others:
If changing an existing definition: