Typescript support was officially added to Svelte with Version 3.0. But what does that actually mean and how can we improve our libraries to get even better typescript support? Let's find out:
Basic typescript support
Getting started is easy, just follow these steps. What you get are the following things:
- you can write typescript in the
section of your svelte components if you add<script>
.lang="ts"
- code can be put into
files in your project.ts
- a rollup preprocess is added to the project, which will transpile typescript to typescript during the build
- the VS Code plugin will show some info about the components, when you call them in other components
the first three bullet points say that Typescript with Svelte compiles. You got the benefit of type checking in your scripts. The last bullet point is about convenience, how much your code editor is able to help you writing code. As an example, consider the following component:
// MagicEightBall.svelte <script lang="ts"> export let question : string = ""; export let personality : number = 7; const responses = Array(3 + personality) .fill('NO') .concat(Array(3 + (14 - personality)).fill('YES')) .concat(['ASK LATER', '???']); let answer = ''; const getAnswer = () => { answer = responses[ question.split('') .reduce((p, v) => p + v.charCodeAt(0), 13) % responses.length ]; }; </script> <figure on:click={getAnswer}> {#if answer.length > 0} <p>{answer}</p> {/if} </figure>
It is a Magic 8 Ball component, which takes a question as input and pseudo-randomly returns an answer from a list of responses, in most cases
or YES
. Try it out here, eg. type "Does my cat love me" and click on the ball (try all caps if you are unhappy with the result):
NO
>check out this tutorial for the style of the 8-Ball
Assume that you would want to include the MagicEightBall component in your project. The code is not long, you could work with it as is. Some documentation would be nice, eg. a readme file that explains the usage. It would be even nicer if the documentation would appear directly in the code editor. To achieve this, add a comment starting with
and the keyword <!--
:
@component
// MagicEightBall.svelte <!-- @component ### Magic 8-Ball A magic 8-Ball component, which channels mystical sources from beyond the grave in a pseudo-random, replicable fashion. - @param question string: A yes/no question. - @param personality number from 1 to 13: The personality of the user. 1 is very positive, 13 is super negative. For best performance it is recommended to combine user data from facebook, social security and healthcare, apply convolutional and recurrent neural networks to categorize user characteristics. --> <script lang="ts"> ... </script> ...
If you add the
component in a different svelte file and hover over it, VS code (or possibly other editors) will show the description. Note that you can use markup syntax to style the output. Interesting information about the component typically includes:
<MagicEightBall/>
- the exported props
- type and valid ranges for the prop
- does the component intend to change the prop, so that it would make sense to use
?bind:
- is the prop optional or mandatory?
- is there a default value?
- emitted events
- named and default slot
Advanced Documentation
In my example above, there is a lot of text dedicated to the
prop. If you have a complicated component with many props, the description can become very long and inefficient. Wouldn't it be better to display only general information on the component description and show detailed information, when you add the attribute? Unfortunately, that does not seem to work out-of-the-box with the current version of Svelte Language Tools. It is possible though, when you add a custom type declaration personality
-file. For the example 8-Ball the file could look like this:
.d.ts
import { SvelteComponentTyped} from 'svelte'; /** ### Magic 8-Ball A magic 8-Ball component, which channels mystical sources from beyond the grave in a pseudo-random, replicable fashion. - @param question string : A yes/no question question. - @param personality number from 1 to 13 : The personality of the user. */ export default class MagicEightBall extends SvelteTypedComponent<MagicEightBallProps, {},{}> {} export declare type MagicEightBallProps: { /** A Yes/No question you have on your heart. Default: empty string */ question : string?, /** The personality of the user. Possible values: 1 - 13. 1 is very positive, 13 is super negative. For best performance it is recommended to combine user data from facebook, social security and healthcare, apply convolutional and recurrent neural networks to categorize user characteristics. Default: 7 */ personality: number? };
The first line imports the base type for Svelte components. This definition was added only recently, so update your project if it is missing. The comment starting with
directly before the class definition will be shown when you hover over /**
, and the comments for the props will show when you add the attributes.
To generate the basic .d.ts files, the script svelte-types-writer. Just see the instructions there. If you want to see this in action, have a look at Smelte (github). Alternatively there is now another script in svelte2dts.
<MagicEightBall
Alternative typing strategy
With Svelte it is easy to integrate web-components. Unfortunately, they often have non-typescript-friendly names, eg. paper-card or wired-input. The naming convention is called kebab-case and it makes it impossible to create types for these components like above. In that case, you can create a file, e.g.
file like this:
types.d.ts
/// <reference path="svelte2tsx/svelte-jsx.d.ts" /> import 'svelte2tsx'; declare global { namespace svelte.JSX { interface IntrinsicElements { /** Component description here */ "magicEightBall":MagicEightBallProps, } interface MagicEightBallProps{ /** A Yes/No question you have on your heart */ question : string?, /** The personality of the user. 1 is very positive, 13 is super negative. ... */ personality: number? } } }
This strategy requires the component to be non-capitalized and it is only recommended, where it is necessary, eg. due to kebab-case. Want to see this in action? Check out svelte-wired-types.
Conclusion
Svelte offers good integration with typescript out of the box. There are tools available to make it easier for users to apply to your libraries.
Share this article on twitter - Vote on next topics - Support me
This might also be interesting for you:
- How to Implement Custom React Hooks in Svelte
- React Hooks in Svelte
- tree-shake-css - project page
- Sveltes tick is my new best friend - porting react-textfit to Svelte
- How to merge cells with svelte-window
- Porting React to Svelte - From react-window 1:1 to svelte-window
- Poll: Which React library would you love to see in Svelte?
- Porting React components to Svelte - It might be easier than you think
- Why are component libraries so complicated with React compared to Svelte?
- How this blog is made - Basic Structure, Elder and Markdown
- How this blog is made part 2 - Make your website sketchy with Tailwind and Roughjs
- Showcase: The Descent Ripple Effect or The React Descent Ripple Effect