Skip to content

Commit f5b7d03

Browse files
authored
Merge pull request #136 from cexbrayat/chore/strict-ts-stubs
chore(stubs): proper typings
2 parents 0bff3eb + bdfc1d3 commit f5b7d03

File tree

2 files changed

+36
-25
lines changed

2 files changed

+36
-25
lines changed

src/dataMixin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export const createDataMixin = (data: Record<string, unknown>) => {
44
return {
55
created() {
66
for (const [k, v] of Object.entries(data)) {
7-
getCurrentInstance().data = { ...getCurrentInstance().data, [k]: v }
7+
getCurrentInstance()!.data = { ...getCurrentInstance()!.data, [k]: v }
88
}
99
}
1010
}

src/stubs.ts

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,37 @@
1-
import { transformVNodeArgs, h, createVNode } from 'vue'
1+
import {
2+
transformVNodeArgs,
3+
h,
4+
ComponentPublicInstance,
5+
Slots,
6+
ComponentOptions,
7+
defineComponent,
8+
VNodeProps,
9+
VNodeTypes
10+
} from 'vue'
211
import { hyphenate } from './utils/vueShared'
312
import { MOUNT_COMPONENT_REF, MOUNT_PARENT_NAME } from './constants'
413
import { config } from './config'
514
import { matchName } from './utils/matchName'
615

7-
interface IStubOptions {
16+
interface StubOptions {
817
name?: string
918
props: any
1019
}
1120

12-
type VNodeArgs = Parameters<typeof createVNode>
13-
14-
function getSlots(ctx) {
21+
function getSlots(ctx: ComponentPublicInstance): Slots | undefined {
1522
return !config.renderStubDefaultSlot ? undefined : ctx.$slots
1623
}
1724

18-
const createStub = ({ name, props }: IStubOptions) => {
25+
const createStub = ({ name, props }: StubOptions): ComponentOptions => {
1926
const anonName = 'anonymous-stub'
2027
const tag = name ? `${hyphenate(name)}-stub` : anonName
2128

22-
const render = (ctx) => {
23-
return h(tag, {}, getSlots(ctx))
29+
const render = (ctx: ComponentPublicInstance) => {
30+
// TS is not happy with this signature, so we cast the Slots as any
31+
return h(tag, {}, getSlots(ctx) as any)
2432
}
2533

26-
return { name: name || anonName, render, props }
34+
return defineComponent({ name: name || anonName, render, props })
2735
}
2836

2937
const resolveComponentStubByName = (
@@ -45,41 +53,45 @@ const resolveComponentStubByName = (
4553
}
4654
}
4755

48-
const isHTMLElement = (args: VNodeArgs) => typeof args[0] === 'string'
56+
const isHTMLElement = (type: VNodeTypes) => typeof type === 'string'
4957

50-
const isCommentOrFragment = (args: VNodeArgs) => typeof args[0] === 'symbol'
58+
const isCommentOrFragment = (type: VNodeTypes) => typeof type === 'symbol'
5159

52-
const isParent = (args: VNodeArgs) =>
53-
isComponent(args) && args[0]['name'] === MOUNT_PARENT_NAME
60+
const isParent = (type: VNodeTypes) =>
61+
isComponent(type) && type['name'] === MOUNT_PARENT_NAME
5462

55-
const isMountedComponent = (args: VNodeArgs) =>
56-
isComponent(args) && args[1] && args[1]['ref'] === MOUNT_COMPONENT_REF
63+
const isMountedComponent = (
64+
type: VNodeTypes,
65+
props: ({ [key: string]: unknown } & VNodeProps) | null | undefined
66+
) => isComponent(type) && props && props['ref'] === MOUNT_COMPONENT_REF
5767

58-
const isComponent = (args: VNodeArgs) => typeof args[0] === 'object'
68+
const isComponent = (type: VNodeTypes): type is ComponentOptions =>
69+
typeof type === 'object'
5970

60-
const isFunctionalComponent = ([type]: VNodeArgs) =>
71+
const isFunctionalComponent = (type: VNodeTypes): type is ComponentOptions =>
6172
typeof type === 'function' && ('name' in type || 'displayName' in type)
6273

6374
export function stubComponents(
6475
stubs: Record<any, any> = {},
6576
shallow: boolean = false
6677
) {
6778
transformVNodeArgs((args) => {
79+
const [nodeType, props, children, patchFlag, dynamicProps] = args
80+
const type = nodeType as VNodeTypes
6881
// args[0] can either be:
6982
// 1. a HTML tag (div, span...)
7083
// 2. An object of component options, such as { name: 'foo', render: [Function], props: {...} }
7184
// Depending what it is, we do different things.
7285
if (
73-
isHTMLElement(args) ||
74-
isCommentOrFragment(args) ||
75-
isParent(args) ||
76-
isMountedComponent(args)
86+
isHTMLElement(type) ||
87+
isCommentOrFragment(type) ||
88+
isParent(type) ||
89+
isMountedComponent(type, props)
7790
) {
7891
return args
7992
}
8093

81-
if (isComponent(args) || isFunctionalComponent(args)) {
82-
const [type, props, children, patchFlag, dynamicProps] = args
94+
if (isComponent(type) || isFunctionalComponent(type)) {
8395
const name = type['name'] || type['displayName']
8496
if (!name && !shallow) {
8597
return args
@@ -97,7 +109,6 @@ export function stubComponents(
97109
// where the signature is h(Component, props, slots)
98110
// case 1: default stub
99111
if (stub === true || shallow) {
100-
// @ts-ignore
101112
const propsDeclaration = type?.props || {}
102113
return [
103114
createStub({ name, props: propsDeclaration }),

0 commit comments

Comments
 (0)