Skip to content

Commit 4cc9ca8

Browse files
authored
types(defineComponent): support for GlobalComponents, typed Directives and respect expose on defineComponent (#3399)
close #3367
1 parent 0e6e3c7 commit 4cc9ca8

File tree

15 files changed

+533
-86
lines changed

15 files changed

+533
-86
lines changed

packages/dts-test/componentTypeExtensions.test-d.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
import { defineComponent } from 'vue'
1+
import { type DefineComponent, type Directive, defineComponent } from 'vue'
22
import { expectType } from './utils'
33

44
declare module 'vue' {
55
interface ComponentCustomOptions {
66
test?(n: number): void
77
}
88

9+
interface GlobalDirectives {
10+
test: Directive
11+
}
12+
13+
interface GlobalComponents {
14+
RouterView: DefineComponent<{}>
15+
}
16+
917
interface ComponentCustomProperties {
1018
state?: 'stopped' | 'running'
1119
}
@@ -46,6 +54,8 @@ export const Custom = defineComponent({
4654
},
4755
})
4856

57+
expectType<Directive>(Custom.directives!.test)
58+
expectType<DefineComponent<{}>>(Custom.components!.RouterView)
4959
expectType<JSX.Element>(<Custom baz={1} />)
5060
expectType<JSX.Element>(<Custom custom={1} baz={1} />)
5161
expectType<JSX.Element>(<Custom bar="bar" baz={1} />)

packages/dts-test/defineComponent.test-d.tsx

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,18 +1501,108 @@ describe('should work when props type is incompatible with setup returned type '
15011501

15021502
describe('withKeys and withModifiers as pro', () => {
15031503
const onKeydown = withKeys(e => {}, [''])
1504+
// @ts-expect-error invalid modifiers
15041505
const onClick = withModifiers(e => {}, [''])
15051506
;<input onKeydown={onKeydown} onClick={onClick} />
15061507
})
15071508

1509+
// #3367 expose components types
1510+
describe('expose component types', () => {
1511+
const child = defineComponent({
1512+
props: {
1513+
a: String,
1514+
},
1515+
})
1516+
1517+
const parent = defineComponent({
1518+
components: {
1519+
child,
1520+
child2: {
1521+
template: `<div></div>`,
1522+
},
1523+
},
1524+
})
1525+
1526+
expectType<typeof child>(parent.components!.child)
1527+
expectType<Component>(parent.components!.child2)
1528+
1529+
// global components
1530+
expectType<Readonly<KeepAliveProps>>(
1531+
new parent.components!.KeepAlive().$props,
1532+
)
1533+
expectType<Readonly<KeepAliveProps>>(new child.components!.KeepAlive().$props)
1534+
1535+
// runtime-dom components
1536+
expectType<Readonly<TransitionProps>>(
1537+
new parent.components!.Transition().$props,
1538+
)
1539+
expectType<Readonly<TransitionProps>>(
1540+
new child.components!.Transition().$props,
1541+
)
1542+
})
1543+
1544+
describe('directive typing', () => {
1545+
const customDirective: Directive = {
1546+
created(_) {},
1547+
}
1548+
1549+
const comp = defineComponent({
1550+
props: {
1551+
a: String,
1552+
},
1553+
directives: {
1554+
customDirective,
1555+
localDirective: {
1556+
created(_, { arg }) {
1557+
expectType<string | undefined>(arg)
1558+
},
1559+
},
1560+
},
1561+
})
1562+
1563+
expectType<typeof customDirective>(comp.directives!.customDirective)
1564+
expectType<Directive>(comp.directives!.localDirective)
1565+
1566+
// global directive
1567+
expectType<typeof vShow>(comp.directives!.vShow)
1568+
})
1569+
1570+
describe('expose typing', () => {
1571+
const Comp = defineComponent({
1572+
expose: ['a', 'b'],
1573+
props: {
1574+
some: String,
1575+
},
1576+
data() {
1577+
return { a: 1, b: '2', c: 1 }
1578+
},
1579+
})
1580+
1581+
expectType<Array<'a' | 'b'>>(Comp.expose!)
1582+
1583+
const vm = new Comp()
1584+
// internal should still be exposed
1585+
vm.$props
1586+
1587+
expectType<number>(vm.a)
1588+
expectType<string>(vm.b)
1589+
1590+
// @ts-expect-error shouldn't be exposed
1591+
vm.c
1592+
})
1593+
15081594
import type {
15091595
AllowedComponentProps,
15101596
ComponentCustomProps,
15111597
ComponentOptionsMixin,
15121598
DefineComponent,
1599+
Directive,
15131600
EmitsOptions,
15141601
ExtractPropTypes,
1602+
KeepAliveProps,
1603+
TransitionProps,
15151604
VNodeProps,
1605+
vShow,
15161606
} from 'vue'
15171607

15181608
// code generated by tsc / vue-tsc, make sure this continues to work
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { type Directive, type ObjectDirective, vModelText } from 'vue'
2+
import { describe, expectType } from './utils'
3+
4+
type ExtractBinding<T> = T extends (
5+
el: any,
6+
binding: infer B,
7+
vnode: any,
8+
prev: any,
9+
) => any
10+
? B
11+
: never
12+
13+
declare function testDirective<
14+
Value,
15+
Modifiers extends string = string,
16+
Arg extends string = string,
17+
>(): ExtractBinding<Directive<any, Value, Modifiers, Arg>>
18+
19+
describe('vmodel', () => {
20+
expectType<ObjectDirective<any, any, 'trim' | 'number' | 'lazy', string>>(
21+
vModelText,
22+
)
23+
// @ts-expect-error
24+
expectType<ObjectDirective<any, any, 'not-valid', string>>(vModelText)
25+
})
26+
27+
describe('custom', () => {
28+
expectType<{
29+
value: number
30+
oldValue: number | null
31+
arg?: 'Arg'
32+
modifiers: Record<'a' | 'b', boolean>
33+
}>(testDirective<number, 'a' | 'b', 'Arg'>())
34+
35+
expectType<{
36+
value: number
37+
oldValue: number | null
38+
arg?: 'Arg'
39+
modifiers: Record<'a' | 'b', boolean>
40+
// @ts-expect-error
41+
}>(testDirective<number, 'a', 'Arg'>())
42+
43+
expectType<{
44+
value: number
45+
oldValue: number | null
46+
arg?: 'Arg'
47+
modifiers: Record<'a' | 'b', boolean>
48+
// @ts-expect-error
49+
}>(testDirective<number, 'a' | 'b', 'Argx'>())
50+
51+
expectType<{
52+
value: number
53+
oldValue: number | null
54+
arg?: 'Arg'
55+
modifiers: Record<'a' | 'b', boolean>
56+
// @ts-expect-error
57+
}>(testDirective<string, 'a' | 'b', 'Arg'>())
58+
})

packages/runtime-core/src/apiDefineComponent.ts

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@ import type {
66
ComponentOptionsWithArrayProps,
77
ComponentOptionsWithObjectProps,
88
ComponentOptionsWithoutProps,
9+
ComponentProvideOptions,
910
ComputedOptions,
1011
MethodOptions,
1112
RenderFunction,
1213
} from './componentOptions'
1314
import type {
1415
AllowedComponentProps,
16+
Component,
1517
ComponentCustomProps,
18+
GlobalComponents,
19+
GlobalDirectives,
1620
SetupContext,
1721
} from './component'
1822
import type {
@@ -29,6 +33,7 @@ import type {
2933
CreateComponentPublicInstance,
3034
} from './componentPublicInstance'
3135
import type { SlotsType } from './componentSlots'
36+
import type { Directive } from './directives'
3237

3338
export type PublicProps = VNodeProps &
3439
AllowedComponentProps &
@@ -55,6 +60,10 @@ export type DefineComponent<
5560
Props = ResolveProps<PropsOrPropOptions, E>,
5661
Defaults = ExtractDefaultPropTypes<PropsOrPropOptions>,
5762
S extends SlotsType = {},
63+
LC extends Record<string, Component> = {},
64+
Directives extends Record<string, Directive> = {},
65+
Exposed extends string = string,
66+
Provide extends ComponentProvideOptions = ComponentProvideOptions,
5867
> = ComponentPublicInstanceConstructor<
5968
CreateComponentPublicInstance<
6069
Props,
@@ -69,7 +78,10 @@ export type DefineComponent<
6978
Defaults,
7079
true,
7180
{},
72-
S
81+
S,
82+
LC & GlobalComponents,
83+
Directives & GlobalDirectives,
84+
Exposed
7385
>
7486
> &
7587
ComponentOptionsBase<
@@ -85,7 +97,11 @@ export type DefineComponent<
8597
Defaults,
8698
{},
8799
string,
88-
S
100+
S,
101+
LC & GlobalComponents,
102+
Directives & GlobalDirectives,
103+
Exposed,
104+
Provide
89105
> &
90106
PP
91107

@@ -166,9 +182,13 @@ export function defineComponent<
166182
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
167183
E extends EmitsOptions = {},
168184
EE extends string = string,
169-
S extends SlotsType = {},
170185
I extends ComponentInjectOptions = {},
171186
II extends string = string,
187+
S extends SlotsType = {},
188+
LC extends Record<string, Component> = {},
189+
Directives extends Record<string, Directive> = {},
190+
Exposed extends string = string,
191+
Provide extends ComponentProvideOptions = ComponentProvideOptions,
172192
>(
173193
options: ComponentOptionsWithoutProps<
174194
Props,
@@ -182,7 +202,11 @@ export function defineComponent<
182202
EE,
183203
I,
184204
II,
185-
S
205+
S,
206+
LC,
207+
Directives,
208+
Exposed,
209+
Provide
186210
>,
187211
): DefineComponent<
188212
Props,
@@ -197,7 +221,11 @@ export function defineComponent<
197221
PublicProps,
198222
ResolveProps<Props, E>,
199223
ExtractDefaultPropTypes<Props>,
200-
S
224+
S,
225+
LC,
226+
Directives,
227+
Exposed,
228+
Provide
201229
>
202230

203231
// overload 3: object format with array props declaration
@@ -216,6 +244,10 @@ export function defineComponent<
216244
S extends SlotsType = {},
217245
I extends ComponentInjectOptions = {},
218246
II extends string = string,
247+
LC extends Record<string, Component> = {},
248+
Directives extends Record<string, Directive> = {},
249+
Exposed extends string = string,
250+
Provide extends ComponentProvideOptions = ComponentProvideOptions,
219251
Props = Readonly<{ [key in PropNames]?: any }>,
220252
>(
221253
options: ComponentOptionsWithArrayProps<
@@ -230,7 +262,11 @@ export function defineComponent<
230262
EE,
231263
I,
232264
II,
233-
S
265+
S,
266+
LC,
267+
Directives,
268+
Exposed,
269+
Provide
234270
>,
235271
): DefineComponent<
236272
Props,
@@ -245,7 +281,11 @@ export function defineComponent<
245281
PublicProps,
246282
ResolveProps<Props, E>,
247283
ExtractDefaultPropTypes<Props>,
248-
S
284+
S,
285+
LC,
286+
Directives,
287+
Exposed,
288+
Provide
249289
>
250290

251291
// overload 4: object format with object props declaration
@@ -262,9 +302,13 @@ export function defineComponent<
262302
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
263303
E extends EmitsOptions = {},
264304
EE extends string = string,
265-
S extends SlotsType = {},
266305
I extends ComponentInjectOptions = {},
267306
II extends string = string,
307+
S extends SlotsType = {},
308+
LC extends Record<string, Component> = {},
309+
Directives extends Record<string, Directive> = {},
310+
Exposed extends string = string,
311+
Provide extends ComponentProvideOptions = ComponentProvideOptions,
268312
>(
269313
options: ComponentOptionsWithObjectProps<
270314
PropsOptions,
@@ -278,7 +322,11 @@ export function defineComponent<
278322
EE,
279323
I,
280324
II,
281-
S
325+
S,
326+
LC,
327+
Directives,
328+
Exposed,
329+
Provide
282330
>,
283331
): DefineComponent<
284332
PropsOptions,
@@ -293,7 +341,11 @@ export function defineComponent<
293341
PublicProps,
294342
ResolveProps<PropsOptions, E>,
295343
ExtractDefaultPropTypes<PropsOptions>,
296-
S
344+
S,
345+
LC,
346+
Directives,
347+
Exposed,
348+
Provide
297349
>
298350

299351
// implementation, close to no-op

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy