Repository: mdx-js/mdx-analyzer
Pull request #366 (2023-12-12 14:45:38)

Enhance how the Props type is used
### Initial checklist

*   [x] I read the support docs <!-- https://github.com/unifiedjs/.github/blob/main/support.md -->
*   [x] I read the contributing guide <!-- https://github.com/unifiedjs/.github/blob/main/contributing.md -->
*   [x] I agree to follow the code of conduct <!-- https://github.com/unifiedjs/.github/blob/main/code-of-conduct.md -->
*   [x] I searched issues and couldn’t find anything (or linked relevant results below) <!-- https://github.com/search?q=user%3Aunifiedjs&type=Issues -->
*   [x] If applicable, I’ve added docs and tests

### Description of changes

If the Props type isn’t defined, it now falls back to an empty shape instead of any. Also all keys are marked as readonly. As a result, props are no longer represented using the string `Props`, but an inline representation of the shape of the props.

Given that the upcoming support for an MDX layout also requires a patched version of `Props`, this new setup is more consistent.

Also the `props` description now contains a link to the props page on the MDX website.

<!--do not edit: pr-->


changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: b0eb87f8f4bb5e7df14560dca8cd117accca1c1a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/mdx-js/mdx-analyzer/new/enhance-props-types?filename=.changeset/heavy-fishes-bow.md&value=---%0A%22%40mdx-js%2Flanguage-server%22%3A%20patch%0A%22%40mdx-js%2Flanguage-service%22%3A%20patch%0A---%0A%0AEnhance%20how%20the%20Props%20type%20is%20used%0A)



Patch:
diff --git a/.changeset/tame-moles-type.md b/.changeset/tame-moles-type.md
new file mode 100644
index 0000000..bef1104
--- /dev/null
+++ b/.changeset/tame-moles-type.md
@@ -0,0 +1,5 @@
+---
+"@mdx-js/language-service": patch
+---
+
+Prettify props types in hover
diff --git a/packages/language-service/lib/language-module.js b/packages/language-service/lib/language-module.js
index a6b2d39..bc30b1b 100644
--- a/packages/language-service/lib/language-module.js
+++ b/packages/language-service/lib/language-module.js
@@ -20,8 +20,8 @@ const componentStart = `
 /**
  * Render the MDX contents.
  *
- * @param {MDXContentProps} props
- *   The props that have been passed to the MDX component.
+ * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props
+ *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.
  */
 export default function MDXContent(props) {
   return `
@@ -29,7 +29,7 @@ const componentEnd = `
 }
 
 // @ts-ignore
-/** @typedef {Props} MDXContentProps */
+/** @typedef {0 extends 1 & Props ? {} : Props} MDXContentProps */
 `
 
 const fallback = componentStart + componentEnd


Test patch:
diff --git a/packages/language-server/test/diagnostics.test.js b/packages/language-server/test/diagnostics.test.js
index dc1c465..9db6520 100644
--- a/packages/language-server/test/diagnostics.test.js
+++ b/packages/language-server/test/diagnostics.test.js
@@ -38,23 +38,11 @@ test('type errors', async () => {
           version: 1
         },
         message:
-          "Property 'counter' may not exist on type 'Props'. Did you mean 'count'?",
+          "Property 'counter' may not exist on type '{ readonly count: number; }'. Did you mean 'count'?",
         range: {
           start: {line: 14, character: 51},
           end: {line: 14, character: 58}
         },
-        relatedInformation: [
-          {
-            location: {
-              range: {
-                start: {line: 11, character: 4},
-                end: {line: 12, character: 2}
-              },
-              uri: fixtureUri('node16/type-errors.mdx')
-            },
-            message: "'count' is declared here."
-          }
-        ],
         severity: 4,
         source: 'ts'
       },
diff --git a/packages/language-service/test/language-module.js b/packages/language-service/test/language-module.js
index 437c3a7..e624f67 100644
--- a/packages/language-service/test/language-module.js
+++ b/packages/language-service/test/language-module.js
@@ -63,15 +63,15 @@ test('create virtual file w/ mdxjsEsm', () => {
           '/**',
           ' * Render the MDX contents.',
           ' *',
-          ' * @param {MDXContentProps} props',
-          ' *   The props that have been passed to the MDX component.',
+          ' * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props',
+          ' *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.',
           ' */',
           'export default function MDXContent(props) {',
           '  return <></>',
           '}',
           '',
           '// @ts-ignore',
-          '/** @typedef {Props} MDXContentProps */',
+          '/** @typedef {0 extends 1 & Props ? {} : Props} MDXContentProps */',
           ''
         )
       },
@@ -137,7 +137,7 @@ test('create virtual file w/ mdxFlowExpression', () => {
         mappings: [
           {
             sourceOffsets: [0],
-            generatedOffsets: [188],
+            generatedOffsets: [275],
             lengths: [9],
             data: {
               completion: true,
@@ -154,15 +154,15 @@ test('create virtual file w/ mdxFlowExpression', () => {
           '/**',
           ' * Render the MDX contents.',
           ' *',
-          ' * @param {MDXContentProps} props',
-          ' *   The props that have been passed to the MDX component.',
+          ' * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props',
+          ' *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.',
           ' */',
           'export default function MDXContent(props) {',
           '  return <>{Math.PI}</>',
           '}',
           '',
           '// @ts-ignore',
-          '/** @typedef {Props} MDXContentProps */',
+          '/** @typedef {0 extends 1 & Props ? {} : Props} MDXContentProps */',
           ''
         )
       },
@@ -235,7 +235,7 @@ test('create virtual file w/ mdxJsxFlowElement w/ children', () => {
         mappings: [
           {
             sourceOffsets: [0, 57],
-            generatedOffsets: [188, 206],
+            generatedOffsets: [275, 293],
             lengths: [9, 8],
             data: {
               completion: true,
@@ -252,8 +252,8 @@ test('create virtual file w/ mdxJsxFlowElement w/ children', () => {
           '/**',
           ' * Render the MDX contents.',
           ' *',
-          ' * @param {MDXContentProps} props',
-          ' *   The props that have been passed to the MDX component.',
+          ' * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props',
+          ' *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.',
           ' */',
           'export default function MDXContent(props) {',
           '  return <><div>',
@@ -264,7 +264,7 @@ test('create virtual file w/ mdxJsxFlowElement w/ children', () => {
           '}',
           '',
           '// @ts-ignore',
-          '/** @typedef {Props} MDXContentProps */',
+          '/** @typedef {0 extends 1 & Props ? {} : Props} MDXContentProps */',
           ''
         )
       },
@@ -330,7 +330,7 @@ test('create virtual file w/ mdxJsxFlowElement w/o children', () => {
         mappings: [
           {
             sourceOffsets: [0],
-            generatedOffsets: [188],
+            generatedOffsets: [275],
             lengths: [7],
             data: {
               completion: true,
@@ -347,15 +347,15 @@ test('create virtual file w/ mdxJsxFlowElement w/o children', () => {
           '/**',
           ' * Render the MDX contents.',
           ' *',
-          ' * @param {MDXContentProps} props',
-          ' *   The props that have been passed to the MDX component.',
+          ' * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props',
+          ' *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.',
           ' */',
           'export default function MDXContent(props) {',
           '  return <><div /></>',
           '}',
           '',
           '// @ts-ignore',
-          '/** @typedef {Props} MDXContentProps */',
+          '/** @typedef {0 extends 1 & Props ? {} : Props} MDXContentProps */',
           ''
         ),
         typescript: {
@@ -424,7 +424,7 @@ test('create virtual file w/ mdxJsxTextElement', () => {
         mappings: [
           {
             sourceOffsets: [2],
-            generatedOffsets: [194],
+            generatedOffsets: [281],
             lengths: [7],
             data: {
               completion: true,
@@ -441,15 +441,15 @@ test('create virtual file w/ mdxJsxTextElement', () => {
           '/**',
           ' * Render the MDX contents.',
           ' *',
-          ' * @param {MDXContentProps} props',
-          ' *   The props that have been passed to the MDX component.',
+          ' * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props',
+          ' *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.',
           ' */',
           'export default function MDXContent(props) {',
           "  return <><>{''}<div /></></>",
           '}',
           '',
           '// @ts-ignore',
-          '/** @typedef {Props} MDXContentProps */',
+          '/** @typedef {0 extends 1 & Props ? {} : Props} MDXContentProps */',
           ''
         )
       },
@@ -514,7 +514,7 @@ test('create virtual file w/ mdxTextExpression', () => {
         },
         mappings: [
           {
-            generatedOffsets: [194],
+            generatedOffsets: [281],
             sourceOffsets: [4],
             lengths: [9],
             data: {
@@ -532,15 +532,15 @@ test('create virtual file w/ mdxTextExpression', () => {
           '/**',
           ' * Render the MDX contents.',
           ' *',
-          ' * @param {MDXContentProps} props',
-          ' *   The props that have been passed to the MDX component.',
+          ' * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props',
+          ' *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.',
           ' */',
           'export default function MDXContent(props) {',
           "  return <><>{''}{Math.PI}{''}</></>",
           '}',
           '',
           '// @ts-ignore',
-          '/** @typedef {Props} MDXContentProps */',
+          '/** @typedef {0 extends 1 & Props ? {} : Props} MDXContentProps */',
           ''
         )
       },
@@ -606,15 +606,15 @@ test('create virtual file w/ syntax error', () => {
           '/**',
           ' * Render the MDX contents.',
           ' *',
-          ' * @param {MDXContentProps} props',
-          ' *   The props that have been passed to the MDX component.',
+          ' * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props',
+          ' *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.',
           ' */',
           'export default function MDXContent(props) {',
           '  return ',
           '}',
           '',
           '// @ts-ignore',
-          '/** @typedef {Props} MDXContentProps */',
+          '/** @typedef {0 extends 1 & Props ? {} : Props} MDXContentProps */',
           ''
         ),
         typescript: {
@@ -669,15 +669,15 @@ test('create virtual file w/ yaml frontmatter', () => {
           '/**',
           ' * Render the MDX contents.',
           ' *',
-          ' * @param {MDXContentProps} props',
-          ' *   The props that have been passed to the MDX component.',
+          ' * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props',
+          ' *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.',
           ' */',
           'export default function MDXContent(props) {',
           '  return <></>',
           '}',
           '',
           '// @ts-ignore',
-          '/** @typedef {Props} MDXContentProps */',
+          '/** @typedef {0 extends 1 & Props ? {} : Props} MDXContentProps */',
           ''
         ),
         typescript: {
@@ -772,15 +772,15 @@ test('update virtual file', () => {
           '/**',
           ' * Render the MDX contents.',
           ' *',
-          ' * @param {MDXContentProps} props',
-          ' *   The props that have been passed to the MDX component.',
+          ' * @param {{readonly [K in keyof MDXContentProps]: MDXContentProps[K]}} props',
+          ' *   The [props](https://mdxjs.com/docs/using-mdx/#props) that have been passed to the MDX component.',
           ' */',
           'export default function MDXContent(props) {',
           "  return <><>{''}</></>",
           '}',
           '',
           '// @ts-ignore',
-          '/** @typedef {Props} MDXContentProps */',
+          '/** @typedef {0 extends 1 & Props ? {} : Props} MDXContentProps */',
           ''
         ),
         typescript: {