@@ -8,9 +8,10 @@ To improve DX and autocompletion of a components' properties, it is possible to
88
99``` ts
1010class Base <BaseInterface extends {
11- $options: BaseOptions ;
12- $refs: BaseRefs ;
13- $children: BaseChildren ;
11+ $el: HTMLElement ;
12+ $options: Record <string , any >;
13+ $refs: Record <string , HTMLElement | HTMLElement []>;
14+ $children: Record <string , Base | Promise <Base >>;
1415}>
1516```
1617
@@ -20,7 +21,9 @@ See below for an example of how to define the type parameter in JSDoc or in Type
2021This guide assumes that you are familiar with [TypeScript types ](https :// www.typescriptlang.org/), make sure to read the basics before going any further.
2122:::
2223
23- ## With JSDoc comments
24+ ## Basic types
25+
26+ ### With JSDoc comments
2427
2528```js
2629import { Base } from ' @studiometa/js-toolkit' ;
@@ -30,7 +33,8 @@ import { Figure } from '@studiometa/ui';
3033 * @typedef {{ name: string, lazy: boolean }} ComponentOptions
3134 * @typedef {{ btn: HTMLButtonElement, items: HTMLElement[] }} ComponentRefs
3235 * @typedef {{ Figure: Figure, LazyComponent: Promise<LazyComponent> }} ComponentChildren
33- * @extends {Base<{ $options: ComponentOptions, $refs: ComponentRefs, $children: ComponentChildren }>}
36+ * @typedef {{ $el: HTMLAnchorElement, $options: ComponentOptions, $refs: ComponentRefs, $children: ComponentChildren }} ComponentInterface
37+ * @extends {Base<ComponentInterface>}
3438 */
3539export default class Component extends Base {
3640 static config = {
@@ -47,6 +51,7 @@ export default class Component extends Base {
4751 };
4852
4953 mounted() {
54+ this .$el ; // HTMLAnchorElement
5055 this .$refs .btn ; // HTMLButtonElement
5156 this .$refs .items ; // HTMLElement[]
5257 this .$options .name ; // string
@@ -57,33 +62,30 @@ export default class Component extends Base {
5762}
5863```
5964
60- ## With TypeScript
65+ ### With TypeScript
6166
6267``` ts
6368import { Base } from ' @studiometa/js-toolkit' ;
6469import { Figure } from ' @studiometa/ui' ;
6570import type LazyComponent from ' ./LazyComponent.js' ;
6671
67- type ComponentOptions {
68- name: string;
69- lazy : boolean ;
70- }
71-
72- type ComponentRefs {
73- btn: HTMLButtonElement;
74- items : HTMLElement [];
75- }
76-
77- type ComponentChildren {
78- Figure: Figure;
79- LazyComponent : Promise < LazyComponent >
80- }
72+ type ComponentInterface = {
73+ $el: HTMLAnchorElement ;
74+ $options: {
75+ name: string ;
76+ lazy: boolean ;
77+ };
78+ $refs: {
79+ btn: HTMLButtonElement ;
80+ items: HTMLElement [];
81+ };
82+ $children: {
83+ Figure: Figure ;
84+ LazyComponent: Promise <LazyComponent >;
85+ };
86+ };
8187
82- export default class Component extends Base <{
83- $options: ComponentOptions ,
84- $refs: ComponentRefs ,
85- $children: ComponentChildren ,
86- }> {
88+ export default class Component extends Base <ComponentInterface > {
8789 static config = {
8890 name: ' Component' ,
8991 refs: [' btn' , ' items[]' ],
@@ -98,6 +100,7 @@ export default class Component extends Base<{
98100 };
99101
100102 mounted() {
103+ this .$el ; // HTMLAnchorElement
101104 this .$refs .btn ; // HTMLButtonElement
102105 this .$refs .items ; // HTMLElement[]
103106 this .$options .name ; // string
@@ -107,3 +110,63 @@ export default class Component extends Base<{
107110 }
108111}
109112```
113+
114+ ## Typing for extensibility
115+
116+ If you create a component that can be extended by other component, you will need to define a type parameter for it.
117+
118+ ### With JSDoc comments
119+
120+ You will need to declare types in a separate comment from the class and import the ` BaseTypeParameter ` type from the ` @studiometa/js-toolkit ` package.
121+
122+ ``` js {2,10,11}
123+ /**
124+ * @typedef {import('@studiometa/js-toolkit').BaseTypeParameter} BaseTypeParameter
125+ * @typedef {{ name: string, lazy: boolean }} ComponentOptions
126+ * @typedef {{ btn: HTMLButtonElement, items: HTMLElement[] }} ComponentRefs
127+ * @typedef {{ Figure: Figure, LazyComponent: Promise<LazyComponent> }} ComponentChildren
128+ * @typedef {{ $el: HTMLAnchorElement, $options: ComponentOptions, $refs: ComponentRefs, $children: ComponentChildren }} ComponentInterface
129+ */
130+
131+ /**
132+ * @template {BaseTypeParameter} [Interface={}]
133+ * @extends {Base<Interface & ComponentInterface>}
134+ */
135+ export default class Component extends Base {
136+ // ...
137+ }
138+ ```
139+
140+ You will then be able to use the ` Component ` class like the ` Base ` class:
141+
142+ ``` js
143+ import Component from ' ./Component.js' ;
144+
145+ /**
146+ * @extends {Component<{ $el: HTMLButtonElement >}}
147+ */
148+ export default class ChildComponent extends Component {
149+ // ...
150+ }
151+ ```
152+
153+ ### With TypeScript
154+
155+ ``` ts
156+ import { Base } from ' @studiometa/js-toolkit' ;
157+ import type { BaseTypeParameter } from ' @studiometa/js-toolkit' ;
158+
159+ export default class Component <Interface extends BaseTypeParameter = {}> extends Base <
160+ Interface & ComponentInterface
161+ > {
162+ // ...
163+ }
164+ ```
165+
166+ ``` ts
167+ import Component from ' ./Component.js' ;
168+
169+ export default class ChildComponent extends Component <{ $el: HTMLButtonElement }> {
170+ // ...
171+ }
172+ ```
0 commit comments