rasti 4.1.0-alpha.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -14
- package/package.json +1 -1
- package/types/Component.d.ts +2 -2
- package/types/Model.d.ts +1 -1
- package/types/index.d.ts +3 -3
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<picture>
|
|
3
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.1.0
|
|
4
|
-
<img alt="Rasti.js" src="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.1.0
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.1.0/docs/logo-dark.svg">
|
|
4
|
+
<img alt="Rasti.js" src="https://cdn.jsdelivr.net/gh/8tentaculos/rasti@v4.1.0/docs/logo.svg" height="120">
|
|
5
5
|
</picture>
|
|
6
6
|
</p>
|
|
7
7
|
|
|
@@ -288,7 +288,7 @@ class Scoreboard extends Component<{}, ScoreState> {
|
|
|
288
288
|
|
|
289
289
|
### Models
|
|
290
290
|
|
|
291
|
-
Type the attributes with `Model<
|
|
291
|
+
Type the attributes with `Model<YourAttrs>`. Use **declaration merging** to surface the auto-generated getters/setters as instance properties:
|
|
292
292
|
|
|
293
293
|
```ts
|
|
294
294
|
import { Model } from 'rasti';
|
|
@@ -314,29 +314,37 @@ t.on('change:completed', (m, value) => value && /* boolean */ console.log('done'
|
|
|
314
314
|
import {
|
|
315
315
|
EventHandler,
|
|
316
316
|
RenderExpression,
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
317
|
+
ModelAttrs,
|
|
318
|
+
ComponentProps,
|
|
319
|
+
ComponentState,
|
|
320
320
|
ComponentModel,
|
|
321
321
|
} from 'rasti';
|
|
322
322
|
|
|
323
|
+
// `Counter` (defined above with Component.create) is a *value*. To use the name in
|
|
324
|
+
// type position, alias it once — now `Counter` is both a value and a type:
|
|
325
|
+
type Counter = InstanceType<typeof Counter>;
|
|
326
|
+
|
|
323
327
|
// Typed event handler with `this` bound to the component
|
|
324
328
|
const onClick: EventHandler<Counter, MouseEvent> = function(ev) {
|
|
325
|
-
this.props.
|
|
329
|
+
this.props.initial;
|
|
326
330
|
};
|
|
327
331
|
|
|
328
332
|
// Typed render expression (`(component) => any`)
|
|
329
|
-
const renderLabel: RenderExpression<Counter> = ({ props }) => props.
|
|
333
|
+
const renderLabel: RenderExpression<Counter> = ({ props }) => props.initial;
|
|
330
334
|
|
|
331
335
|
// Extract types from existing classes
|
|
332
|
-
type
|
|
333
|
-
type P =
|
|
334
|
-
type S =
|
|
336
|
+
type A = ModelAttrs<Todo>; // Todo extends Model → already a type, no alias
|
|
337
|
+
type P = ComponentProps<Counter>; // pass the instance; `ComponentProps<typeof Counter>` is `never`
|
|
338
|
+
type S = ComponentState<Counter>;
|
|
335
339
|
```
|
|
336
340
|
|
|
341
|
+
> Components made with `Component.create` are **values**, not types. To use one as a type — as with `Counter` above — add `type X = InstanceType<typeof X>` next to the definition, or write `InstanceType<typeof X>` inline. A `Model` subclass needs no alias, since `class` already declares both a value and a type.
|
|
342
|
+
|
|
337
343
|
### Typing template interpolations
|
|
338
344
|
|
|
339
|
-
Functions inside a template are `any` — rasti can't infer them from the surrounding string.
|
|
345
|
+
Functions inside a template are `any` — rasti can't infer them from the surrounding string. Which type to use depends on how rasti treats the function (quoted attribute or content → run on render; unquoted attribute → passed as-is):
|
|
346
|
+
|
|
347
|
+
> Under `strict` / `noImplicitAny`, every interpolation callback **must** be annotated — an untyped parameter is an error (TS7031/TS7006), not a silent `any`. In non-strict mode typing is opt-in: annotate where you want safety and leave trivial ones as `any`.
|
|
340
348
|
|
|
341
349
|
| Interpolation | What it is | Type to use |
|
|
342
350
|
|---|---|---|
|
|
@@ -347,6 +355,12 @@ Functions inside a template are `any` — rasti can't infer them from the surrou
|
|
|
347
355
|
Three ways to apply them:
|
|
348
356
|
|
|
349
357
|
```ts
|
|
358
|
+
// `Home` is a value (made with Component.create), so alias it to use the name as a type:
|
|
359
|
+
const Home = Component.create<{}, { location: string }>`<div></div>`.extend({
|
|
360
|
+
close() { /* ... */ },
|
|
361
|
+
});
|
|
362
|
+
type Home = InstanceType<typeof Home>;
|
|
363
|
+
|
|
350
364
|
// 1. Named const — cleanest for non-trivial handlers
|
|
351
365
|
const onClick: EventHandler<Home, MouseEvent> = function(ev, self) {
|
|
352
366
|
ev.preventDefault();
|
|
@@ -354,10 +368,10 @@ const onClick: EventHandler<Home, MouseEvent> = function(ev, self) {
|
|
|
354
368
|
};
|
|
355
369
|
|
|
356
370
|
// 2. Inline with `satisfies` — checks + types the params without widening
|
|
357
|
-
${(({ state }) => state
|
|
371
|
+
${(({ state }) => state?.location) satisfies RenderExpression<Home>}
|
|
358
372
|
|
|
359
373
|
// 3. Bare annotation — lightest, just types the argument
|
|
360
|
-
${({ state }: Home) => state
|
|
374
|
+
${({ state }: Home) => state?.location}
|
|
361
375
|
```
|
|
362
376
|
|
|
363
377
|
For a function passed to a child, neither helper fits — its type comes from the child's prop. Type it against that prop's declared type (rasti can't connect the attribute to the child, since both live inside the template string):
|
package/package.json
CHANGED
package/types/Component.d.ts
CHANGED
|
@@ -71,9 +71,9 @@ export type EventHandler<C, E extends Event = Event> = (
|
|
|
71
71
|
export type RenderExpression<C> = (this: C, component: C) => any;
|
|
72
72
|
|
|
73
73
|
/** Extracts the props type `P` from a Component subclass. */
|
|
74
|
-
export type
|
|
74
|
+
export type ComponentProps<C> = C extends Component<infer P, any, any> ? P : never;
|
|
75
75
|
/** Extracts the state type `S` from a Component subclass. */
|
|
76
|
-
export type
|
|
76
|
+
export type ComponentState<C> = C extends Component<any, infer S, any> ? S : never;
|
|
77
77
|
/** Extracts the model type `M` from a Component / View subclass. */
|
|
78
78
|
export type ComponentModel<C> =
|
|
79
79
|
C extends Component<any, any, infer M> ? M :
|
package/types/Model.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Emitter from './Emitter.js';
|
|
2
2
|
|
|
3
3
|
/** Extracts the attribute type `A` from a Model subclass. */
|
|
4
|
-
export type
|
|
4
|
+
export type ModelAttrs<M> = M extends Model<infer A> ? A : never;
|
|
5
5
|
|
|
6
6
|
export type ModelEvents<A> =
|
|
7
7
|
& {
|
package/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { default as Emitter, EventMap } from './Emitter.js';
|
|
2
|
-
export { default as Model, ModelEvents,
|
|
2
|
+
export { default as Model, ModelEvents, ModelAttrs } from './Model.js';
|
|
3
3
|
export { default as View, ViewOptions } from './View.js';
|
|
4
4
|
export {
|
|
5
5
|
default as Component,
|
|
@@ -9,8 +9,8 @@ export {
|
|
|
9
9
|
ComponentPartial,
|
|
10
10
|
EventHandler,
|
|
11
11
|
RenderExpression,
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
ComponentProps,
|
|
13
|
+
ComponentState,
|
|
14
14
|
ComponentModel,
|
|
15
15
|
ComponentLifecycle,
|
|
16
16
|
ExtendedComponent,
|