-
Notifications
You must be signed in to change notification settings - Fork 0
Schema
The types can be defined according to the following schema. The root element is always <types>
which generally includes N <type>
and <method>
elements. A type can be:
-
<interface>
for interfaces, most suitable to define interfaces of classes. -
<constructor>
which is not used much. -
<record>
for objects without a class, like configs.
The type will then have N <prop>
or <property>
elements each describing a prop. A member of a type which is a function can also be written as <function>
or <fn>
.
Additionally, a <method>
is used to describe exported functions from a packages. Therefore, the meaning of method is that an independent API member, whereas a function is a property of a class (i.e. the reverse traditional meaning).
export const method = (arg, arg2) => {
// this is a method as it's exported by package
}
/**
* @implements {namespace.Example}
*/
class Example {
// this is a function as a member of class
function() {
}
}
We define methods in XML files also, so that templates can be generated.
Finally, an <embed>
element can be used to automatically include types from the specified locations in the generated typedefs. This is useful for vendoring, when types from 3rd party packages need to be included in package's own types because during compilation, the source code is merged and no dependencies will be installed when consuming the package. Therefore, to preserve types, they need to be embedded. This could be done manually with markers like /* typal node_modules/@3rdparty/package/types/index.xml
however the embed
element simplifies the process.
<types
namespace="_namespace">
<import .../>
<type ...>...</type>
</types>
The single root element for the XML file.
-
namespace
[optional]: how all types will be prefixed in the source code and externs. The use of namespaces is generally only needed for when using GCC to prevent clashes of types, e.g., it is common to name the config objects "Config". The namespace will typically start with_
to also prevent variable name clashes with extern namespaces.// SOURCE.js // The first line is to enable exporting via VSCode's typedef import. /** * @typedef {_restream.Rule} Rule The replacement rule. */ // The second line is to use within the source file, so that the externs // match the annotated type. /** * @typedef {Object} _namespace.Rule The replacement rule. */ /** * @param {_namespace.Rule} rule */ function hello(rule) {} // EXTERNS.js /** @const */ var _namespace = {} /** @typedef { myType: boolean } */ _namespace.Type
The type represents a JSDoc type.
<type
name="Type"
desc="The description of the type."
type="(name: string) => number"
constructor interface record
extends="_namespace.ParentType"
closure="function(string): number">
<prop name="...">...</prop>
</type>
-
name
: [required]: the name of the type. -
desc
[optional]: the optional description. -
type
[optional]: what is the type, defaultObject
. -
constructor
[optional]: for externs, adds the@constructor
annotation and declares the properties via the prototype.Show Prototype Notation
/* typal example/schema/constructor.xml */ /** @const */ var _test = {} /** * The example type. * @extends {_ns.ParentType} * @constructor */ _test.Test /** * A prop. * @type {boolean|undefined} */ _test.Test.prototype.bool
-
interface
[optional]: for externs, same as@constructor
, but adds the@interface
annotation. -
record
[optional]: for externs, same as@constructor
, but adds the@record
annotation. This type is called Structural Interfaces and is the best choice for configs etc. Types without@constructor
/@interface
/@record
in externs will be presented as{{ a: string, b: number }}
but when denoted with@record
, externs will have the same meaning, but will be easier to read. However,@record
types can be nullable, whereas simple{{ record }}
types are explicitly non-nullable. -
extends
[optional]: forconstructors
,interfaces
andrecords
this allows to inherit properties from the parent types (see above).Show Extends Notation
Extends Type (view extends.xml) /* typal example/schema/extends.xml */ /** * @suppress {nonStandardJsDocs} * @typedef {_test.Test} Test `@record` The example type. */ /** * @suppress {nonStandardJsDocs} * @typedef {_test.$Test & _ns.ParentType} _test.Test `@record` The example type. */ /** * @suppress {nonStandardJsDocs} * @typedef {Object} _test.$Test `@record` The example type. * @prop {boolean} [bool] A prop. */
JSDoc typedefs will contain an extra class denoted with $
to be able to extend the parent class, because there's no other way to do it: if the typedef had the parent in its type notation (instead of{Object}
), then the properties wouldn't be applied. The internal$
class is then merged with the parent class using the&
symbol which is TypeScript-specific, but understood by VSCode (not part of the JSDoc spec, but should be)./* typal example/schema/extends.xml */ /** @const */ var _test = {} /** * The example type. * @extends {_ns.ParentType} * @record */ _test.Test /** * A prop. * @type {boolean|undefined} */ _test.Test.prototype.bool
Externs just add the @extends
marker when the type is either@constructor
,@interface
or@record
. -
closure
[optional]: an override of the type when generating doc in closure mode.Show Closure Override
Closure Override (view closure.xml) /* typal example/schema/closure.xml */ /** * @suppress {nonStandardJsDocs} * @typedef {_test.Example} Example */ /** * @suppress {nonStandardJsDocs} * @typedef {function(string): number} _test.Example */
In Closure mode, Typal will print the value of the closure
property. This is helpful for displaying user-readable documentation in README files, but using the types for compilation. There's no way to use both in source code (i.e., the standard type for VSCode and the closure type for GCC)./* typal example/schema/closure.xml */ /** * @typedef {(s: string) => number} Example */
In standard mode, only the type
attribute is displayed. This is not compatible with GCC, therefore should only be used for JSDoc approach programming.
The properties are found inside of the Type
elements. At the moment, the must have a description, otherwise the parsing won't work.
<prop
name="property"
string boolean number type="Type"
opt default="The default value"
closure="_ns.Type">
Property Description.
</prop>
-
name
: the name of the property. -
string
[optional]: sets the type to bestring
. -
boolean
[optional]: sets the type to beboolean
. -
number
[optional]: sets the type to benumber
. -
type
[optional]: sets the type of the property. Default*
. -
opt
[optional]: whether the property is optional. In externs this will result in{ prop: (string|undefined) }
. -
default
[optional]: the default value of the property. Used to add theDefault: value.
to the property description, and@param {type} [prop=default]
when annotating JS functions. -
closure
[optional]: an override of the type when generating doc in closure mode. -
example
[optional]: the comma-separated paths to examples (e.g.,example/jsdoc/hello.js,example/jsdoc/world.js
). When starts with.
, the paths are resolved relative to the type file. The content of examples can be wrapped like so:import test from 'test' function run() { /* start example */ test('hello') /// A triple slash lines will break the example code block /// and appear as normal text. test('world') /* end example */ }
-
example-override
[optional]: the comma-separated overrides for imports in examples, e.g.,../../src => @scope/package
. This allows to print user-friendly examples to documentation, and execute examples as the same time. -
template-no-return
[optional]: when generating templates for constructors, this will prevent their return type (deprecated).
Properties (view property.xml) |
---|
<types>
<type name="Example">
<prop boolean name="boolean">The boolean property.</prop>
<prop number name="number">The number property.</prop>
<prop string name="string">The string property.</prop>
<prop type="Example" name="example">The custom type property.</prop>
<prop opt type="Example" name="optional">The optional property.</prop>
<prop string name="default" default="hello">
The default property.
</prop>
<prop type="Example" closure="_ns.Example" name="closure">
The Closure override property.
</prop>
<prop string name="example"
example="example/schema/jsdoc.js"
example-override="../src => typal">
A property with an example.
</prop>
</type>
</types> |
The properties are listed inside of types and must have descriptions which are trimmed. |
/* typal example/schema/property.xml */
/**
* @typedef {Object} Example
* @prop {boolean} boolean The boolean property.
* @prop {number} number The number property.
* @prop {string} string The string property.
* @prop {Example} example The custom type property.
* @prop {Example} [optional] The optional property.
* @prop {string} [default="hello"] The default property. Default `hello`.
* @prop {Example} closure The Closure override property.
* @prop {string} example A property with an example.
* ```js
* import typal from 'typal'
*
* ```
* standard logging
* ```js
* typal('hello world')
*
* ```
* verbose logging
* ```js
* typal('', { verbose: true })
* ```
*/ |
Typal will extract properties from xml file and insert them into JSDoc. |
import outsideExample from 'rqt'
/* start example */ import typal from '../src'
/// standard logging
typal('hello world')
/// verbose logging
typal('', { verbose: true }) /* end example */ |
The examples can take advantage of /* start/end example */ markers and imports renaming. |
<import
name="Type"
from="package-name/src"
ns="_packageName"
link="https://docs.page/package-name"
desc="The imported type from another package.">
</import>
-
name
: the name of the imported type. -
from
: the package (restream
) or path (restream/src/Rule
) to import from. -
ns
[optional]: if different from the path, the namespace with which the type will be imported. -
link
[optional]: the link to display in documentation with Documentary. -
desc
[optional]: the description to print in documentation.
Imports (view import.xml) |
---|
/* typal example/schema/import.xml */
/**
* @typedef {import('restream').Rule} Rule
* @typedef {import('restream/src/markers').Marker} Marker
* @typedef {import('stream').Readable} Readable
*/ |
In standard mode, Typal does not use namespaces. |
/* typal example/schema/import.xml */
/**
* @suppress {nonStandardJsDocs}
* @typedef {import('restream').Rule} _restream.Rule
*/
/**
* @suppress {nonStandardJsDocs}
* @typedef {import('restream/src/markers').Marker} _restream.Marker
*/
/**
* @suppress {nonStandardJsDocs}
* @typedef {import('stream').Readable} stream.Readable
*/ |
In Closure mode, Typal adds namespaces so that they will match externs. |
Any additional types that need to be put in the source code can be added with the <embed>
method. This will generate automatic /* typal-embed location.xml ...args */
marker in the source code but without a line break, so that it is managed by Typal.
<embed
src="location.xml"
path="location.xml"
ignore="_ns.Ignored,_ns2.Ignored"
closure namespace externs no-supprss>
</import>
The only required attribute is either src
or path
that point to the XML file to read for embedding. A new marker will inherit all attributes from its parent, e.g., if the parent used extern
, the new one will also have externs
. This is because they are used in the same file. If, for some reason, they need to be explicitly overridden, new values can also be passed.
-
src
: the path to the XML file. -
path
: alternative attribute name tosrc
. -
ignore
[optional]: comma-separated list of types to ignore. -
closure
[optional]: generate Closure types. -
namespace
[optional]: use namespace (VSCode typedefs). -
externs
[optional]: generate externs.
<types>
<embed src="example/schema/extends.xml" namespace />
<type name="MyType" extends="_test.Test" desc="A custom type.">
<prop string name="example">
Hello World.
</prop>
</type>
</types> |
/* typal example/schema/embed.xml namespace */
/**
* @typedef {$MyType & _test.Test} MyType A custom type.
* @typedef {Object} $MyType A custom type.
* @prop {string} example Hello World.
*/
/* typal-embed example/schema/extends.xml namespace */
/**
* @typedef {_test.Test} Test `@record` The example type.
* @typedef {_test.$Test & _ns.ParentType} _test.Test `@record` The example type.
* @typedef {Object} _test.$Test `@record` The example type.
* @prop {boolean} [bool] A prop.
*/ |
Embeds are mostly used in typedefs, but should be skipped in externs as the compiler will discover the externs during compilation. To prevent embeds, the no-embed
(or noEmbed
) attribute should be set on the parent market.
/* typal types/index.xml externs no-embed */
// no embedding will take place
© Art Deco 2020 | Tech Nation Visa Sucks |
---|