From c1cdd5265c30806df13bd2e4cde0d4de2503efcf Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Tue, 23 Apr 2024 11:52:41 +0200 Subject: [PATCH] Fix type errors Since typical usage of `unified-lint-rule` involves inferring the type based on a function call, the inferred type should be public. If private types are used, TypeScript will generate types for dependant packages that use relative paths. To solve this, public types in `unified-lint-rule` were moved from `lib/index.js` to `index.js`. `lintRule` only uses these public types. The severity can be set as a boolean. To support this, the `Label` type now accepts a boolean type. Two tests explicitly test bad input. These are annotated with a `@ts-expect-error` comment. --- packages/unified-lint-rule/index.js | 36 ++++++++++++-- packages/unified-lint-rule/lib/index.js | 63 +++++-------------------- test.js | 2 + 3 files changed, 46 insertions(+), 55 deletions(-) diff --git a/packages/unified-lint-rule/index.js b/packages/unified-lint-rule/index.js index f44fed37..7a76d0b7 100644 --- a/packages/unified-lint-rule/index.js +++ b/packages/unified-lint-rule/index.js @@ -111,15 +111,41 @@ */ /** - * @typedef {import('./lib/index.js').Label} Label - * @typedef {import('./lib/index.js').Meta} Meta - * @typedef {import('./lib/index.js').Severity} Severity + * @typedef {'error' | 'on' | 'off' | 'warn' | boolean} Label + * Severity label; + * `'off'`: `0`, `'on'` and `warn`: `1`, `'error'`: `2`. + */ + +/** + * @typedef Meta + * Rule metadata. + * @property {string} origin + * Name of the lint rule. + * @property {string | null | undefined} [url] + * Link to documentation (optional). + */ + +/** + * @typedef {0 | 1 | 2} Severity + * Severity number; + * `0`: `'off'`, `1`: `'on'` and `warn`, `2`: `'error'`. */ /** * @template {Node} [Tree=Node] - * @template {any} [Options=unknown] - * @typedef {import('./lib/index.js').Rule} Rule + * Node kind (optional). + * @template {any} [Option=unknown] + * Parameter kind (optional). + * @callback Rule + * Rule. + * @param {Tree} tree + * Tree. + * @param {import('vfile').VFile} file + * File. + * @param {Option} option + * Parameter. + * @returns {Promise | undefined | void} + * Nothing. */ export {lintRule} from './lib/index.js' diff --git a/packages/unified-lint-rule/lib/index.js b/packages/unified-lint-rule/lib/index.js index f1de97f6..7a000e74 100644 --- a/packages/unified-lint-rule/lib/index.js +++ b/packages/unified-lint-rule/lib/index.js @@ -1,57 +1,29 @@ /** * @typedef {import('unist').Node} Node - * @typedef {import('vfile').VFile} VFile */ /** - * @typedef {'error' | 'on' | 'off' | 'warn'} Label - * Severity label; - * `'off'`: `0`, `'on'` and `warn`: `1`, `'error'`: `2`. - * - * @typedef Meta - * Rule metadata. - * @property {string} origin - * Name of the lint rule. - * @property {string | null | undefined} [url] - * Link to documentation (optional). - * - * @typedef {0 | 1 | 2} Severity - * Severity number; - * `0`: `'off'`, `1`: `'on'` and `warn`, `2`: `'error'`. - * - * @typedef {[severity: Severity, ...parameters: Array]} SeverityTuple + * @typedef {[severity: import('../index.js').Severity, ...parameters: Array]} SeverityTuple * Parsed severty and options. */ -/** - * @template {Node} [Tree=Node] - * Node kind (optional). - * @template {any} [Option=unknown] - * Parameter kind (optional). - * @callback Rule - * Rule. - * @param {Tree} tree - * Tree. - * @param {VFile} file - * File. - * @param {Option} option - * Parameter. - * @returns {Promise | undefined | void} - * Nothing. - */ - import {wrap} from 'trough' /** * @template {Node} [Tree=Node] * Node kind. - * @template {any} [Option=unknown] + * @template {any} [Option=never] * Parameter kind. - * @param {Meta | string} meta + * @param {import('../index.js').Meta | string} meta * Info. - * @param {Rule} rule + * @param {import('../index.js').Rule} rule * Rule. - * @returns + * @returns {import('unified').Plugin<[( + * | [level: import('../index.js').Label | import('../index.js').Severity, option?: Option] + * | import('../index.js').Label + * | Option + * | import('../index.js').Severity + * )?], Tree>} * Plugin. */ export function lintRule(meta, rule) { @@ -64,12 +36,13 @@ export function lintRule(meta, rule) { Object.defineProperty(plugin, 'name', {value: id}) + // @ts-expect-error Not sure what’s going on here, but it works. return plugin /** - * @param {[level: Label | Severity, option?: Option] | Label | Option | Severity} [config] + * @param {[level: import('../index.js').Label | import('../index.js').Severity, option?: Option] | import('../index.js').Label | Option | import('../index.js').Severity} [config] * Config. - * @returns + * @returns {import('unified').Transformer | undefined} * Transform, if on. */ function plugin(config) { @@ -79,16 +52,6 @@ export function lintRule(meta, rule) { if (!severity) return - /** - * @param {Tree} tree - * Tree. - * @param {VFile} file - * File. - * @param {import('unified').TransformCallback} next - * Next. - * @returns {undefined} - * Nothing. - */ return function (tree, file, next) { let index = file.messages.length - 1 diff --git a/test.js b/test.js index 58afe09e..ad523bb8 100644 --- a/test.js +++ b/test.js @@ -232,6 +232,7 @@ test('remark-lint', async function (t) { 'should fail on incorrect severities (too high)', async function () { assert.throws(function () { + // @ts-expect-error This tests an incorrect severity. remark().use(remarkLintFinalNewline, [3]).freeze() }, /^Error: Incorrect severity `3` for `final-newline`, expected 0, 1, or 2$/) } @@ -241,6 +242,7 @@ test('remark-lint', async function (t) { 'should fail on incorrect severities (too low)', async function () { assert.throws(function () { + // @ts-expect-error This tests an incorrect severity. remark().use(remarkLintFinalNewline, [-1]).freeze() }, /^Error: Incorrect severity `-1` for `final-newline`, expected 0, 1, or 2$/) }