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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Svelte5 JSDoc for $props #10541

Closed
dreitzner opened this issue Feb 19, 2024 · 8 comments · Fixed by #11370
Closed

Svelte5 JSDoc for $props #10541

dreitzner opened this issue Feb 19, 2024 · 8 comments · Fixed by #11370
Milestone

Comments

@dreitzner
Copy link
Contributor

Describe the problem

When declaring props with TS, we can add JSDoc comments and type annotations:

interface Props {
	/**
	 * This is an important optional count
	*/
	count?: number;
}

let { 
	count = 0
} = $props<Props>();

This will show all the info also in intellisense when the component is used:
image

But when not using TS, I don't think there is a way to pass that extra info to the LSP.

Describe the proposed solution

It might be nice to add the possibility to augment the destructured props like this:

let { 
	/**
	 * This is an important optional count
	 * @type {number}
	*/
	count
} = $props();

There might be already a working solution out there, that I'm not aware of....

In that case I'd be happy to add it to the docs :)

Importance

nice to have

@dummdidumm
Copy link
Member

dummdidumm commented Feb 19, 2024

You can use typedef for this:

/**
 * @typedef Props
 * @property {number} count Some documentation
 */

/** @type {Props} */
let { count } = $props();

Giving this the documentation label to note this wherever in the final new docs we're going to talk about typing stuff.

@dummdidumm dummdidumm added this to the 5.0 milestone Feb 19, 2024
@dreitzner
Copy link
Contributor Author

@dummdidumm this does not seem to work at the moment.

If I do a typedef inisde of a normal <script /> block I get the following error:

image

dummdidumm added a commit to sveltejs/language-tools that referenced this issue Feb 20, 2024
Look at the last comment before the node first, check for `@type` and prevent `@typedef` false positive
sveltejs/svelte#10541 (comment)
dummdidumm added a commit to sveltejs/language-tools that referenced this issue Feb 20, 2024
Look at the last comment before the node first, check for `@type` and prevent `@typedef` false positive
sveltejs/svelte#10541 (comment)
@sheijne
Copy link

sheijne commented Feb 20, 2024

@dummdidumm this does not seem to work at the moment.

If I do a typedef inisde of a normal <script /> block I get the following error:

@dreitzner It does work:

Screenshot 2024-02-20 at 20 18 46

Nonetheless the error occurs in different IDE's and is definitely a bug. There are more options though:

  1. Define the type inline with an object literal:
<script>
  /** @type {{ count: number }} */
  let { count } = $props();
</script>

2.a. Define the type in a separate definition file:

// Counter.d.ts

interface CounterProps {
  count: number;
}
// Counter.svelte
<script>
  /** @type {CounterProps} */
  let { count } = $props();
</script>

2.b. Though in most cases it would probably be more useful to make the definition file a module:

// Counter.d.ts

export interface CounterProps {
  count: number;
}
// Counter.svelte

<script>
  /** @type {import('./Counter').CounterProps} */
  let { count } = $props();
</script>
  1. If you really wanted to you could also use <script lang="ts" context="module"> (though it seems the LSP implicitly "adds" lang="ts" to the second script, which in my opinion is a bug):
<script lang="ts" context="module">
  export interface CounterProps {
    count: number;
  }
</script>

<script>
  /** @type {CounterProps} */
  let { count } = $props();
</script>

@dummdidumm
Copy link
Member

The code I gave is correct, there's a bug in the VS Code Svelte extension which I fixed in sveltejs/language-tools#2294, release pending.

@dreitzner
Copy link
Contributor Author

@dummdidumm thank you so much for the explenation and the fix :)

@theetrain
Copy link
Contributor

theetrain commented Apr 26, 2024

The @typedef method works for me. I tried using @param, but was not successful:

<script>
  /**
   * @param {Object} Props
   * @param {string} Props.name
   */
  let { name, age, date } = $props()
</script>

<p>Your {name}</p>
<!--     ^ type is `unknown` -->

Can we allow this method of documentation and typing? It could save a couple of lines.

It seems to work with plain JS: playground.

@brunnerh
Copy link
Member

brunnerh commented Apr 26, 2024

That's invalid syntax, the types just come from inference based on the assigned value.

You can do something like this:

/**
 * @type {{
 *  name: string,
 *  age: number,
 *  ...
 * }}
 */
let { name, age, date } = $props()

@theetrain
Copy link
Contributor

Thanks for educating me; I don't know why I thought @param could be used for anything except functions. I suppose @typedef + @property are ideal for documentation, and @type for just types.

I was hoping @typedef can be applied in one step, but that's not possible. All good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants