René's URL Explorer Experiment


Title: Bring back return type narrowing + fixes by gabritto · Pull Request #61359 · microsoft/TypeScript · GitHub

Open Graph Title: Bring back return type narrowing + fixes by gabritto · Pull Request #61359 · microsoft/TypeScript

X Title: Bring back return type narrowing + fixes by gabritto · Pull Request #61359 · microsoft/TypeScript

Description: Fixes #33014. Fixes #33912. This PR brings back conditional and indexed access return type narrowing from #56941, but with a few updates. The main motivation behind those updates is described in https://gist.github.com/gabritto/b6ebd5f9fc2bb3cfc305027609e66bca, but to put it shortly, type narrowing very often cannot distinguish between two non-primitive types, and since return type narrowing depends on type narrowing to work, it often didn't. Update 1: non-primitive restriction To deal with those problematic type narrowing scenarios, the first update is to disallow narrowing of conditional return types that attempt to distinguish between two non-primitive types. So this example will not work: type QuickPickReturn = T extends { canSelectMultiple: true } ? string[] : T extends { canSelectMultiple: false } ? string : never; type QuickPickOptions = { prompt: string; items: string[]; canSelectMultiple: true; } | { prompt: string; items: string[]; canSelectMultiple: false; } function showQuickPick(options: T): QuickPickReturn { if (options.canSelectMultiple) { return options.items; // Error } return options.items[0]; // Error } That's because the conditional return type QuickPickReturn has one branch with type { canSelectMultiple: true }, which is non-primitive, and another branch with type { canSelectMultiple: false }, which is also non-primitive. However, the following will work: type QuickPickOptions = { prompt: string; items: string[]; canSelectMultiple: T; }; type QuickPickReturn = T extends true ? string[] : T extends false ? string : never; function showQuickPick(options: QuickPickOptions): QuickPickReturn { if (options.canSelectMultiple) { return options.items; } return options.items[0]; } type QuickPickOptions = { prompt: string; items: string[]; }; type QuickPickReturn = T extends string ? string : T extends QuickPickOptions ? string[] : never; function showQuickPick(optionsOrItem: T): QuickPickReturn { if (typeof optionsOrItem === "string") { return optionsOrItem; } return optionsOrItem.items; } Distinguishing between two primitive types or between a primitive and non-primitive type in the conditional type's branches is allowed. Update 2: type parameter embedding We can now detect that a type parameter is a candidate for being used in return type narrowing (i.e. it's a narrowable type parameter) in cases where the type parameter is indirectly used as a type of a parameter or property. Before, only this type of usage of T in a parameter type annotation would be recognized: type PickNumberRet = T extends true ? 1 : T extends false ? 2 : never; function pickNumber(b: T): PickNumberRet { return b ? 1 : 2; } Now, the following also work: type PickNumberRet = T extends true ? 1 : T extends false ? 2 : never; function pickNumber({ b }: { b: T }): PickNumberRet { return b ? 1 : 2; } function pickNumber(opts: { b: T }): PickNumberRet { return opts.b ? 1 : 2; } Combined with the non-primitive restriction mentioned above, this enables users to place narrowable type parameters inside object types at the exact property that is used for narrowing, so instead of writing this: function fun(param: T): ..., users can write this: function fun(param: { prop: T }): .... Note that the analysis done to decide if a type parameter is used the parameter in a way that allows it to be narrowed is a syntactical one. We want to avoid resolving and inspecting actual types during the analysis, because a lot of types are lazy in some sense, and we don't want this analysis to cause unintended side effects, e.g. circularity errors. But this means that any usage of a type parameter that requires semantically resolving types to validate it is not going to work. For a more complete list of what's currently supported here in terms of usages of type parameters, see test tests\cases\compiler\dependentReturnType11.ts. Update 3: relax extends type restriction This is a small improvement unrelated to the previous updates. In the original PR, this was disallowed because we required that a conditional return type's extends types be identical to the types in the type parameter constraint: interface Dog { name: string; bark(): string; } type NormalizedRet = T extends {} ? T : T extends null | undefined ? undefined : never; function normalizeDog(dog: T): NormalizedRet { if (dog == undefined) { return undefined; // Originally an error } return dog; // Originally an error } Note that in NormalizedRet, the first branch's extends type is {}, not Dog, so this wasn't allowed because those types are not identical. With this PR, we only require that a type in the constraint is assignable to the extends type, i.e. that Dog is assignable to {}, so the code above is now allowed for return type narrowing.

Open Graph Description: Fixes #33014. Fixes #33912. This PR brings back conditional and indexed access return type narrowing from #56941, but with a few updates. The main motivation behind those updates is described in ht...

X Description: Fixes #33014. Fixes #33912. This PR brings back conditional and indexed access return type narrowing from #56941, but with a few updates. The main motivation behind those updates is described in ht...

Opengraph URL: https://github.com/microsoft/TypeScript/pull/61359

X: @github

direct link

Domain: github.com

route-pattern/:user_id/:repository/pull/:id/commits/:range(.:format)
route-controllerpull_requests
route-actioncommits
fetch-noncev2:b8f74452-0067-74d0-1ae0-22073d115539
current-catalog-service-hashae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b
request-id9AFC:301411:205E67B:2BE35DB:6A655891
html-safe-nonceb9b108dcb3984080234d740f413b236ab25822615fbdc24fa0fda53ae015cb7b
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5QUZDOjMwMTQxMToyMDVFNjdCOjJCRTM1REI6NkE2NTU4OTEiLCJ2aXNpdG9yX2lkIjoiNzQxMDIyMTc2OTI2NTg3MDI1IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0=
visitor-hmac35ea8179a66e0170cfa4bc0c2d3a7b107b5ce9435f3e3e669dffca63a3890737
hovercard-subject-tagpull_request:2374737243
github-keyboard-shortcutsrepository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///pull_requests/show/commits
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34
twitter:imagehttps://avatars.githubusercontent.com/u/19519347?s=400&v=4
twitter:cardsummary_large_image
og:imagehttps://avatars.githubusercontent.com/u/19519347?s=400&v=4
og:image:altFixes #33014. Fixes #33912. This PR brings back conditional and indexed access return type narrowing from #56941, but with a few updates. The main motivation behind those updates is described in ht...
og:site_nameGitHub
og:typeobject
hostnamegithub.com
expected-hostnamegithub.com
None52c76df668885aaff23b50bdca1fa1ea44ac9c1553e888ebc70ff1e4daa4625b
turbo-cache-controlno-preview
diff-viewunified
go-importgithub.com/microsoft/TypeScript git https://github.com/microsoft/TypeScript.git
octolytics-dimension-user_id6154722
octolytics-dimension-user_loginmicrosoft
octolytics-dimension-repository_id20929025
octolytics-dimension-repository_nwomicrosoft/TypeScript
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id20929025
octolytics-dimension-repository_network_root_nwomicrosoft/TypeScript
turbo-body-classeslogged-out env-production page-responsive full-width
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release309153364422b3c499922d1a2a6404910a58ed8e
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmicrosoft%2FTypeScript%2Fpull%2F61359%2Fcommits%2Fc872eb853c6a895a3be257f22f75a00b0a13ee34
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
Code QualityEnforce quality at mergehttps://github.com/features/code-quality
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmicrosoft%2FTypeScript%2Fpull%2F61359%2Fcommits%2Fc872eb853c6a895a3be257f22f75a00b0a13ee34
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fpull_requests%2Fshow%2Fcommits&source=header-repo&source_repo=microsoft%2FTypeScript
Reloadhttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34
Reloadhttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34
Reloadhttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34
Please reload this pagehttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34
microsoft https://github.com/microsoft
TypeScripthttps://github.com/microsoft/TypeScript
Notifications https://github.com/login?return_to=%2Fmicrosoft%2FTypeScript
Fork 13.6k https://github.com/login?return_to=%2Fmicrosoft%2FTypeScript
Star 110k https://github.com/login?return_to=%2Fmicrosoft%2FTypeScript
Code https://github.com/microsoft/TypeScript
Issues 5k+ https://github.com/microsoft/TypeScript/issues
Pull requests 20 https://github.com/microsoft/TypeScript/pulls
Actions https://github.com/microsoft/TypeScript/actions
Projects https://github.com/microsoft/TypeScript/projects
Models https://github.com/microsoft/TypeScript/models
Wiki https://github.com/microsoft/TypeScript/wiki
Security and quality 0 https://github.com/microsoft/TypeScript/security
Insights https://github.com/microsoft/TypeScript/pulse
Code https://github.com/microsoft/TypeScript
Issues https://github.com/microsoft/TypeScript/issues
Pull requests https://github.com/microsoft/TypeScript/pulls
Actions https://github.com/microsoft/TypeScript/actions
Projects https://github.com/microsoft/TypeScript/projects
Models https://github.com/microsoft/TypeScript/models
Wiki https://github.com/microsoft/TypeScript/wiki
Security and quality https://github.com/microsoft/TypeScript/security
Insights https://github.com/microsoft/TypeScript/pulse
Sign up for GitHub https://github.com/signup?return_to=%2Fmicrosoft%2FTypeScript%2Fissues%2Fnew%2Fchoose
terms of servicehttps://docs.github.com/terms
privacy statementhttps://docs.github.com/privacy
Sign inhttps://github.com/login?return_to=%2Fmicrosoft%2FTypeScript%2Fissues%2Fnew%2Fchoose
gabrittohttps://github.com/gabritto
mainhttps://github.com/microsoft/TypeScript/tree/main
gabritto/fixedcondhttps://github.com/microsoft/TypeScript/tree/gabritto/fixedcond
Conversation 16 https://github.com/microsoft/TypeScript/pull/61359
Commits 12 https://github.com/microsoft/TypeScript/pull/61359/commits
Checks 0 https://github.com/microsoft/TypeScript/pull/61359/checks
Files changed https://github.com/microsoft/TypeScript/pull/61359/files
Please reload this pagehttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34
Bring back return type narrowing + fixes https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#top
Show all changes 12 commits https://github.com/microsoft/TypeScript/pull/61359/files
aa38e34 Revert "Revert return type narrowing (#61136)" gabritto Mar 5, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/aa38e34c18a5a1ed0b5a661abcac7ca3a5061314
073d868 add restriction on narrowable type constraint gabritto Feb 1, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/073d868abed1a1800e14bc0e7ebc42585ee94f76
17ed356 relax restriction on extends type of narrowable conditional type gabritto Feb 1, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/17ed356c580798f88470c359892f59747dba147f
fdb6bea WIP: detect embedded references to a narrowable type parameter gabritto Feb 1, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/fdb6beabee44085a9d61f1777d4eaf8917fb9c9a
1849292 Detect and construct narrowable references for embedded type parameters gabritto Feb 28, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/18492922064d6115f891d1e13a61d24d3cdca9b8
009d152 validate optional param/property gabritto Mar 4, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/009d1524e18d691c8620be9529fa93a1fb967cbb
5cb7e90 format gabritto Mar 5, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/5cb7e902bc1bfab7249a79da5d42f3b174778fe9
3c5327e rework non-primitive restriction to be based on conditional type bran… gabritto Mar 5, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/3c5327e4796874c3e94a4701b0ec72352bc57771
7464af0 update tests gabritto Mar 5, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/7464af0f099eba2aaa6e3073e76f25874ad7b919
c96e01e bring back conditional expression test gabritto Mar 5, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/c96e01e4fe582be7da354bf00752a08287fcedbc
c872eb8 Also support classes. TODO: support parameter properties gabritto Mar 21, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34
2084fa0 fix baselines gabritto Mar 21, 2025 https://github.com/microsoft/TypeScript/pull/61359/commits/2084fa0a24c68ca14b009661eb2c3b9b2e606f40
Clear filters https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34
Please reload this pagehttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34
Please reload this pagehttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34
checker.ts https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-d9ab6589e714c71e657f601cf30ff51dfc607fc98419bf72e04f6b0fa92cc4b8
dependentReturnType11.errors.txt https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-a5ee2347507d3d9bf58bd52c571c4cec9231638d4d3dbea4b2308e6f79f17884
dependentReturnType11.ts https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-aea804e6c093940044bce81458b5407920d4cc070b6b123e4c98014171f46966
Prev https://github.com/microsoft/TypeScript/pull/61359/commits/c96e01e4fe582be7da354bf00752a08287fcedbc
Next https://github.com/microsoft/TypeScript/pull/61359/commits/2084fa0a24c68ca14b009661eb2c3b9b2e606f40
Please reload this pagehttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34
https://github.com/gabritto
gabrittohttps://github.com/microsoft/TypeScript/commits?author=gabritto
src/compiler/checker.tshttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-d9ab6589e714c71e657f601cf30ff51dfc607fc98419bf72e04f6b0fa92cc4b8
View file https://github.com/microsoft/TypeScript/blob/c872eb853c6a895a3be257f22f75a00b0a13ee34/src/compiler/checker.ts
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/microsoft/TypeScript/pull/61359/commits/{{ revealButtonHref }}
https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-d9ab6589e714c71e657f601cf30ff51dfc607fc98419bf72e04f6b0fa92cc4b8
https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-d9ab6589e714c71e657f601cf30ff51dfc607fc98419bf72e04f6b0fa92cc4b8
https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-d9ab6589e714c71e657f601cf30ff51dfc607fc98419bf72e04f6b0fa92cc4b8
https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-d9ab6589e714c71e657f601cf30ff51dfc607fc98419bf72e04f6b0fa92cc4b8
tests/baselines/reference/dependentReturnType11.errors.txthttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-a5ee2347507d3d9bf58bd52c571c4cec9231638d4d3dbea4b2308e6f79f17884
View file https://github.com/microsoft/TypeScript/blob/c872eb853c6a895a3be257f22f75a00b0a13ee34/tests/baselines/reference/dependentReturnType11.errors.txt
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/microsoft/TypeScript/pull/61359/commits/{{ revealButtonHref }}
https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-a5ee2347507d3d9bf58bd52c571c4cec9231638d4d3dbea4b2308e6f79f17884
https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-a5ee2347507d3d9bf58bd52c571c4cec9231638d4d3dbea4b2308e6f79f17884
https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-a5ee2347507d3d9bf58bd52c571c4cec9231638d4d3dbea4b2308e6f79f17884
https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-a5ee2347507d3d9bf58bd52c571c4cec9231638d4d3dbea4b2308e6f79f17884
https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-a5ee2347507d3d9bf58bd52c571c4cec9231638d4d3dbea4b2308e6f79f17884
tests/cases/compiler/dependentReturnType11.tshttps://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-aea804e6c093940044bce81458b5407920d4cc070b6b123e4c98014171f46966
View file https://github.com/microsoft/TypeScript/blob/c872eb853c6a895a3be257f22f75a00b0a13ee34/tests/cases/compiler/dependentReturnType11.ts
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/microsoft/TypeScript/pull/61359/commits/{{ revealButtonHref }}
https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-aea804e6c093940044bce81458b5407920d4cc070b6b123e4c98014171f46966
https://github.com/microsoft/TypeScript/pull/61359/commits/c872eb853c6a895a3be257f22f75a00b0a13ee34#diff-aea804e6c093940044bce81458b5407920d4cc070b6b123e4c98014171f46966
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.