Skip to content

Commit 9e1ca49

Browse files
committed
types: fix mount infer prop type
1 parent 090afc1 commit 9e1ca49

File tree

4 files changed

+93
-42
lines changed

4 files changed

+93
-42
lines changed

src/mount.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,10 @@ export function mount<
104104
Props,
105105
Defaults
106106
>,
107-
options?: MountingOptions<Props, D>
107+
options?: MountingOptions<
108+
Partial<Defaults> & Omit<Props & PublicProps, keyof Defaults>,
109+
D
110+
>
108111
): VueWrapper<
109112
InstanceType<
110113
DefineComponent<

src/types.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
Directive,
55
Plugin,
66
AppConfig,
7-
VNode
7+
VNode,
8+
VNodeProps
89
} from 'vue'
910

1011
interface RefSelector {
@@ -32,7 +33,14 @@ type SlotDictionary = {
3233
[key: string]: Slot
3334
}
3435

35-
export interface MountingOptions<Props, Data = {}> {
36+
type RawProps = VNodeProps & {
37+
// used to differ from a single VNode object as children
38+
__v_isVNode?: never
39+
// used to differ from Array children
40+
[Symbol.iterator]?: never
41+
} & Record<string, any>
42+
43+
export interface MountingOptions<P, Data = {}> {
3644
/**
3745
* Overrides component's default data. Must be a function.
3846
* @see https://vue-test-utils.vuejs.org/v2/api/#data
@@ -42,11 +50,11 @@ export interface MountingOptions<Props, Data = {}> {
4250
* Sets component props when mounted.
4351
* @see https://vue-test-utils.vuejs.org/v2/api/#props
4452
*/
45-
props?: Props
53+
props?: (RawProps & P) | ({} extends P ? null : never)
4654
/**
4755
* @deprecated use `data` instead.
4856
*/
49-
propsData?: Props
57+
propsData?: P
5058
/**
5159
* Sets component attributes when mounted.
5260
* @see https://vue-test-utils.vuejs.org/v2/api/#attrs

test-dts/mount.d-test.ts

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ expectType<string>(
4545
// )
4646

4747
// can not receive extra props
48-
expectError(
49-
mount(AppWithDefine, {
50-
props: { a: 'Hello', c: 2 }
51-
})
52-
)
48+
// expectError(
49+
// mount(AppWithDefine, {
50+
// props: { a: 'Hello', c: 2 }
51+
// })
52+
// )
5353

5454
// wrong prop type should not compile
5555
expectError(
@@ -76,11 +76,11 @@ expectType<string>(
7676
)
7777

7878
// can't receive extra props
79-
expectError(
80-
mount(AppWithProps, {
81-
props: { a: 'Hello', b: 2 }
82-
})
83-
)
79+
// expectError(
80+
// mount(AppWithProps, {
81+
// props: { a: 'Hello', b: 2 }
82+
// })
83+
// )
8484

8585
// wrong prop type should not compile
8686
expectError(
@@ -109,20 +109,20 @@ expectType<number>(
109109
}).vm.b
110110
)
111111

112-
// cannot receive extra props
113-
// if they pass use object inside
114-
expectError(
115-
mount(
116-
{
117-
props: ['a']
118-
},
119-
{
120-
props: {
121-
b: 2
122-
}
123-
}
124-
)
125-
)
112+
// // cannot receive extra props
113+
// // if they pass use object inside
114+
// expectError(
115+
// mount(
116+
// {
117+
// props: ['a']
118+
// },
119+
// {
120+
// props: {
121+
// b: 2
122+
// }
123+
// }
124+
// )
125+
// )
126126

127127
const AppWithoutProps = {
128128
template: ''
@@ -150,7 +150,7 @@ expectError((props: { a: 1 }) => {}, {
150150
})
151151

152152
expectType<number>(
153-
mount((props: { a: 1 }, ctx) => {}, {
153+
mount((props: { a: number }, ctx) => {}, {
154154
props: {
155155
a: 22
156156
}
@@ -226,3 +226,43 @@ class ClassComponent extends Vue {
226226
// @ts-expect-error it requires an argument
227227
expectError(mount(ClassComponent, {}).vm.changeMessage())
228228
mount(ClassComponent, {}).vm.changeMessage('')
229+
230+
// default props
231+
const Foo = defineComponent({
232+
props: {
233+
bar: Boolean,
234+
baz: String
235+
},
236+
template: ''
237+
})
238+
239+
mount(Foo, {
240+
props: {
241+
baz: 'hello'
242+
}
243+
})
244+
245+
mount(Foo, {
246+
props: {
247+
bar: true
248+
}
249+
})
250+
251+
expectError(
252+
mount(
253+
defineComponent({
254+
props: {
255+
baz: String,
256+
bar: {
257+
type: Boolean,
258+
required: true
259+
}
260+
}
261+
}),
262+
{
263+
props: {
264+
baz: 'hello'
265+
}
266+
}
267+
)
268+
)

test-dts/shallowMount.d-test.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ let wrapper = shallowMount(AppWithDefine, {
2121
// vm is properly typed
2222
expectType<string>(wrapper.vm.a)
2323

24-
// can not receive extra props
25-
expectError(
26-
shallowMount(AppWithDefine, {
27-
props: { a: 'Hello', c: 2 }
28-
})
29-
)
24+
// // can not receive extra props
25+
// expectError(
26+
// shallowMount(AppWithDefine, {
27+
// props: { a: 'Hello', c: 2 }
28+
// })
29+
// )
3030

3131
// wrong prop type should not compile
3232
expectError(
@@ -53,12 +53,12 @@ expectType<string>(
5353
}).vm.a
5454
)
5555

56-
// can't receive extra props
57-
expectError(
58-
shallowMount(AppWithProps, {
59-
props: { a: 'Hello', b: 2 }
60-
})
61-
)
56+
// // can't receive extra props
57+
// expectError(
58+
// shallowMount(AppWithProps, {
59+
// props: { a: 'Hello', b: 2 }
60+
// })
61+
// )
6262

6363
// wrong prop type should not compile
6464
expectError(

0 commit comments

Comments
 (0)