JSX and TypeScript
Typed components, and JSX when you have a build step.
TypeScript
Signy is written in TypeScript and ships its types. Signals infer their
type from the first value. A component takes its props as a type
parameter and marks render() and setup() as
protected.
import { Component, Signal, html } from 'signy';
interface BadgeProps {
label: string;
}
class Badge extends Component<BadgeProps> {
private clicks = new Signal(0);
protected render() {
return html`
<button onClick=${() => this.clicks.set((c) => c + 1)}>
${this.props.label} (${() => this.clicks.value})
</button>
`;
}
}
Give a signal an explicit type when the first value does not say enough.
const user = new Signal<User | null>(null);
JSX
JSX is compiled by babel-plugin-jsx-dom-expressions, the
same compiler Solid uses. Calling jsx() at runtime throws,
so setting jsxImportSource alone is not enough.
// babel.config.js
module.exports = {
plugins: [
['babel-plugin-jsx-dom-expressions', {
moduleName: 'signy/jsx',
generate: 'dom',
delegateEvents: true,
wrapConditionals: true,
}],
],
};
With the compiler, {count.value} in JSX is reactive because
the compiler wraps it in a function. The other rules hold:
render() runs once and lists go through For.
class Counter extends Component {
private count = new Signal(0);
protected render() {
return (
<button onClick={() => this.count.set((c) => c + 1)}>
Clicked {this.count.value} times
</button>
);
}
}