Skip to content

Typing Svelte Component Props/Events/Slots [Feedback Thread] #442

Closed
@dummdidumm

Description

@dummdidumm

[this is now the feedback thread]

This was implemented according to this RFC. Please provide feedback about using it in this thread.

Original Post

There are several issues about this already (#424, sveltejs/svelte#304, sveltejs/svelte#273, sveltejs/svelte#263), but I wanted to make a consolidated one to have a discussion about the approaches we can take.
Related PR: sveltejs/svelte#437

Note that this issue is NOT about typing a d.ts file, this will come afterwards as a separate issue.

Is your feature request related to a problem? Please describe.
At the moment it is not possible to type the inputs/outputs of a component under certain circumstances:

  • It is not possible to define a generic relationship between props and events/slots (generics)
  • It is not possible to define the events and their types
  • It is not possible to define the slots and their types in a specific way

Describe the solution you'd like
A way to type props/events/slots explicitly.

Proposal: A new reserved interface ComponentDef which, when defined, is used as the public API of the component instead of infering the things from the code.

Example (with comments about what likely is not possible):

<script lang="ts"
   interface ComponentDef<T> { // <-- note that we can use generics as long as they are "defined" through props
      props: {  items: T[]  }
      events: {  itemClick: CustomEvent<T>  }
      slots: { default: { item: T } }
  }

   // generic type T is not usable here. Is that a good solution? Should it be possible?
   // Also: How do we make sure the types match the component definition?
  export items: any[];

   // ...

   // We cannot make sure that the dispatched event and its type are correct. Is that a problem?
   // Maybe enhance the type definitions in the core repo so createEventDispatcher accepts a record of eventname->type?
   dispatch('itemClick', item);
</script>
<!-- ... -->
<slot item={item}> <!-- again, we cannot make sure this actually matches the type definition -->

When someone now uses the component, he will get the correct types from the props/events/slots and also error diagnostics when something is wrong:

<Child
     items="{['a', 'string']}"
     on:itemClick="{event => event.detail === 1 /* ERROR, number not comparable to type string */}"
/>

If this works and is tested a little, we could enhance it with other reserved interfaces like ComponentEvents to only type one of the things.

I'd like to get as much feedback on this as possible because this is likely a big change which might be used broadly. Also, I'd like to have some of the core team members to have a look at this if this looks good to them or introduces something they don't agree with.

@jasonlyu123 @orta @Conduitry @antony @pngwn

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions