TypeScript
This article is about using TypeScript in the MediaWiki ecosystem. There are many excellent resources for general TypeScript usage elsewhere, some are referenced below.
TypeScript as a JavaScript documentation linter
[edit]The TypeScript executable, tsc
, can be used to lint the documentation in plain JavaScript files.
JSDoc typing
[edit]JSDoc is the preferred way to write JavaScript documentation in MediaWiki software (JSDuck is deprecated). TypeScript can parse and understand JSDocs. A typical type would be documented as:
/**
* Template properties for a portlet.
* @typedef {Object} PortletContext
* @prop {string} portal-id Identifier for wrapper.
* @prop {string} html-tooltip Tooltip message.
* @prop {string} msg-label-id Aria identifier for label text.
* @prop {string} [html-userlangattributes] Additional Element attributes.
* @prop {string} msg-label Aria label text.
* @prop {string} html-portal-content
* @prop {string} [html-after-portal] HTML to inject after the portal.
* @prop {string} [html-hook-vector-after-toolbox] Deprecated and used by the toolbox portal.
*/
And a function would be:
/**
* @param {PortletContext} data The properties to render the portlet template with.
* @return {HTMLElement} The rendered portlet.
*/
function wrapPortlet( data ) {
const node = document.createElement( 'div' );
node.setAttribute( 'id', 'mw-panel' );
node.innerHTML = mustache.render( portalTemplate, data );
return node;
}
The above examples on the TypeScript playground.
Sharing types across files
[edit]- Type definitions (
*.d.ts
) are global scripts by default. - Type definitions become non-global modules if the file contains any
import
s orexport
s. Any types you wish to be globals must be explicitly made so. E.g:
declare global {
interface XY {x: number, y: number}
}
require
s andimport
s bring along their types.- Import types look like
/** @typedef {import('../../math/xy').XY} XY */
.
TypeScript definitions
[edit]TypeScript definitions are a common means to describe and share the documentation and typing information for an entire library such as jQuery. They're also useful more broadly for sharing definitions across files and globals.
An equivalent TypeScript definition (or TSD) of the above type and function (with documentation and implementation stripped) is:
interface PortletContext {
'portal-id': string;
'html-tooltip': string;
'msg-label-id': string;
'html-userlangattributes'?: string;
'msg-label': string;
'html-portal-content': string;
'html-after-portal'?: string;
'html-hook-vector-after-toolbox'?: string;
}
declare function wrapPortlet(data: PortletContext): HTMLElement;
The above examples on the TypeScript playground.
Documentation in TSDs are still JSDocs so it could be identical to the preceding examples (or omit the JSDoc typing). However, TSDs cannot contain implementation as they are not compiled and have no functional impact.
MediaWiki TypeScript definitions
[edit]- An official library exists for documenting MediaWiki core and other common libraries. It includes only a small number of type definitions as of July 2024.
- There are also community-maintained libraries with better coverage:
Note that type definitions can also supply code completion in pure JavaScript projects in popular IDEs.
TypeScript as a compiler
[edit]TypeScript also supports more direct means to describe typing information called annotations. However, this syntax requires TypeScript proper and a compilation step. Examples include (in roughly reverse chronological order):
- Wikidata Bridge (repository) Edit wikidata’s data directly from wikipedia
- wikibase tainted references A part of wikibase UI for statement editing
- wikibase-termbox A part of wikibase item/property page UI, incl. server-side rendering capability
- A (dated) TypeScript Preact prototype
Project setup
[edit]For projects with mixed JavaScript and TypeScript files or only plain JavaScript files, you may wish to include or exclude files until their typing is fully accurate with respect to the documentation. There are several ways to do that including:
- tsconfig.json: add files via the
includes
or remove files via theexcludes
field. More details can be found under compiler options. @ts-check
/@ts-nocheck
: add or remove entire files with a single comment.@ts-ignore
: ignore the errors on a single line. Should generally be used as a temporary fix pointing to a Phabricator ticket, as this can (and has)led to production errors.
Example JavaScript documentation configuration
[edit]{
"exclude": ["docs", "vendor"],
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"newLine": "lf",
"forceConsistentCasingInFileNames": true,
"pretty": true,
"target": "es5",
"lib": ["dom"],
"allowJs": true,
"checkJs": true,
"noEmit": true
}
}
See also
[edit]- The official TypeScript website
- The official JSDoc website
- Type checking JavaScript files (official documentation)
- TypeScript playground (live compiler, contains many useful examples)
- Vue.js TypeScript support