Skip to content

Commit d4c88f1

Browse files
committed
Add ReadonlyArray to types
Related-to: syntax-tree/unist-util-visit-parents#17.
1 parent 2d2d70f commit d4c88f1

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

index.test-d.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import type {Content, Heading, Paragraph, Root} from 'mdast'
1+
import type {Heading, Paragraph, RootContent, Root} from 'mdast'
22
import {expectAssignable, expectNotType, expectType} from 'tsd'
33
import type {Node, Parent} from 'unist'
44
import {convert, is} from 'unist-util-is'
55

66
// # Setup
77

8-
const mdastNode = (function (): Root | Content {
8+
const mdastNode = (function (): Root | RootContent {
99
return {type: 'paragraph', children: []}
1010
})()
1111

@@ -49,6 +49,7 @@ if (is(mdastNode, {type: 'heading', depth: 2})) {
4949
// TS makes this `type: string`.
5050
if (is(mdastNode, {type: 'paragraph'})) {
5151
expectNotType<Heading>(mdastNode)
52+
expectNotType<Paragraph>(mdastNode)
5253
}
5354

5455
if (is(mdastNode, {type: 'paragraph'} as const)) {
@@ -111,6 +112,18 @@ if (is(mdastNode, ['heading', isHeading, isHeadingLoose, {type: 'heading'}])) {
111112
expectNotType<Heading>(mdastNode)
112113
}
113114

115+
// Can’t narrow down.
116+
if (is(mdastNode, ['heading'])) {
117+
expectNotType<Heading>(mdastNode)
118+
expectNotType<Paragraph>(mdastNode)
119+
}
120+
121+
// Can narrow down with `as const` on arrays of strings.
122+
if (is(mdastNode, ['heading'] as const)) {
123+
expectType<Heading>(mdastNode)
124+
expectNotType<Paragraph>(mdastNode)
125+
}
126+
114127
// # `check`
115128

116129
// No node.

lib/index.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/**
2-
* @typedef {import('unist').Node} Node
3-
* @typedef {import('unist').Parent} Parent
2+
* @import {Node, Parent} from 'unist'
43
*/
54

65
/**
@@ -28,7 +27,7 @@
2827
*
2928
* Note: `Node` is included as it is common but is not indexable.
3029
*
31-
* @typedef {Array<Props | TestFunction | string> | Props | TestFunction | string | null | undefined} Test
30+
* @typedef {Array<Props | TestFunction | string> | ReadonlyArray<Props | TestFunction | string> | Props | TestFunction | string | null | undefined} Test
3231
* Check for an arbitrary node.
3332
*
3433
* @callback TestFunction
@@ -67,6 +66,8 @@ export const is =
6766
// Note: overloads in JSDoc can’t yet use different `@template`s.
6867
/**
6968
* @type {(
69+
* (<Condition extends ReadonlyArray<string>>(node: unknown, test: Condition, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node & {type: Condition[number]}) &
70+
* (<Condition extends Array<string>>(node: unknown, test: Condition, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node & {type: Condition[number]}) &
7071
* (<Condition extends string>(node: unknown, test: Condition, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node & {type: Condition}) &
7172
* (<Condition extends Props>(node: unknown, test: Condition, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node & Condition) &
7273
* (<Condition extends TestFunction>(node: unknown, test: Condition, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node & Predicate<Condition, Node>) &
@@ -163,7 +164,11 @@ export const convert =
163164
}
164165

165166
if (typeof test === 'object') {
166-
return Array.isArray(test) ? anyFactory(test) : propertiesFactory(test)
167+
return Array.isArray(test)
168+
? anyFactory(test)
169+
: // Cast because `ReadonlyArray` goes into the above but `isArray`
170+
// narrows to `Array`.
171+
propertiesFactory(/** @type {Props} */ (test))
167172
}
168173

169174
if (typeof test === 'string') {

0 commit comments

Comments
 (0)