sveltejs / language-tools

The Svelte Language Server, and official extensions which use it
MIT License
1.25k stars 200 forks source link

Weird behavior with Generics + SvelteHTMLElement #2271

Open paoloricciuti opened 9 months ago

paoloricciuti commented 9 months ago

Describe the bug

I was creating an "isomorphic component" (basically where you pass as and it render the correct html element) and i started experimenting with the typings to get autocompletion. I come up with this which works fine

<script lang="ts" generics="T extends keyof HTMLElementTagNameMap">
    import type { SvelteHTMLElements } from 'svelte/elements';
    export let as: T;

    type $$Props = SvelteHTMLElements[T] & {
        as: T;
    };
</script>

the typecheck per se works fine but what is a bit iffy it's the autocompletion. You get autocomplete for every prop even the one that are not associated with the type T (for example you get autocomplete for type if you use spam for as). I tried the same generic function in the typescript playground and it works correctly.

https://github.com/sveltejs/language-tools/assets/26281609/1bfdc057-5cb0-42f2-b3b1-d1a0a9886dc8

https://github.com/sveltejs/language-tools/assets/26281609/403a5a65-8d27-4200-b28d-9d76d895fb9d

Reproduction

  1. go to this TS playground https://tsplay.dev/NB1Gpw
  2. verify that autocomplete works correctly
  3. paste the above code in a svelte component in vscode
  4. try to import it and get autocompletion

Expected behaviour

You should only get autocompletion for the correct element

System Info

Which package is the issue about?

No response

Additional Information, eg. Screenshots

No response

jasonlyu123 commented 9 months ago

The generic function isn't the same. The component type is more complex than a simple function. Because of the extra complexity, the completion probably got wrong. Anyway, this will have to be fixed in TypeScript. There is probably not much we can do.

https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBDAnmApnA3nAygNxQGxhQAkAVAWQBkBRfFEFAOxgGc4BfOAMyghDgBELPIRQB6AvSasBAbgBQoSLAzYRRAMJ9IjaR269+Q9Sjnz5AExQBjfAEMoaLgFdG1mMAiM4W8AB5SOBQADyJGCzYAaxRECC44MipaKWZSOwBzADk7BnI7MAA+AAowXjAWAC4MO0q4Uk4AMjUCIkSaOgZmFgBtUgBdAEoqu0ZEBXlbGrZfMAAmAKDQpgi4aNj4tuTOmDSsnJQ8wsWwldwWlBmvaT95OAwAchr7qvq4JrPRTY7pHv75Aow7HMMyK6FucBqVQEdgEABpwQALRxcKECeTsAbjXQAdx82lmoPBpQg5SqYLud0hcHuLDAI3u8IpCGQKCq93u4PYjIQDnSKBgVQsEGszm2ADoAEYQCyIdEDIA

Edit:

I can also see type in your simple version, just not the string literal types completion for the button. You probably hit a state where Monaco returns a cached version of the completion. A level nested is also enough to make the string literals completion for type appear. So, it is probably unrelated to the SvelteComponent but the nested object.

paoloricciuti commented 9 months ago

The generic function isn't the same. The component type is more complex than a simple function. Because of the extra complexity, the completion probably got wrong. Anyway, this will have to be fixed in TypeScript. There is probably not much we can do.

https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBDAnmApnA3nAygNxQGxhQAkAVAWQBkBRfFEFAOxgGc4BfOAMyghDgBELPIRQB6AvSasBAbgBQoSLAzYRRAMJ9IjaR269+Q9Sjnz5AExQBjfAEMoaLgFdG1mMAiM4W8AB5SOBQADyJGCzYAaxRECC44MipaKWZSOwBzADk7BnI7MAA+AAowXjAWAC4MO0q4Uk4AMjUCIkSaOgZmFgBtUgBdAEoqu0ZEBXlbGrZfMAAmAKDQpgi4aNj4tuTOmDSsnJQ8wsWwldwWlBmvaT95OAwAchr7qvq4JrPRTY7pHv75Aow7HMMyK6FucBqVQEdgEABpwQALRxcKECeTsAbjXQAdx82lmoPBpQg5SqYLud0hcHuLDAI3u8IpCGQKCq93u4PYjIQDnSKBgVQsEGszm2ADoAEYQCyIdEDIA

Edit:

I can also see type in your simple version, just not the string literal types completion for the button. You probably hit a state where Monaco returns a cached version of the completion. A level nested is also enough to make the string literals completion for type appear. So, it is probably unrelated to the SvelteComponent but the nested object.

Oh yeah i tought that could've been the case but didn't think of ways to test it...thanks for the playground