Skip to content

Commit 8f876de

Browse files
authored
feat(volar/jsx-directive): support expose for vapor functional components (#997)
* fix(volar/jsx-directive): unwrap exposed for vapor functional components * chore: add test * chore: update * chore: update * fix: typecheck * chore: remove NonNullable * fix: exclude __ctx * chore: update
1 parent 5e51a17 commit 8f876de

File tree

4 files changed

+39
-15
lines changed

4 files changed

+39
-15
lines changed

packages/volar/src/jsx-directive/context.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@ export function resolveCtxMap(
1818
): Map<import('typescript').Node, string> {
1919
if (ctxNodeMap.size) {
2020
options.codes.push(`
21-
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false; type __VLS_PickNotAny<A, B> = __VLS_IsAny<A> extends true ? B : A;
21+
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false;
22+
type __VLS_PickNotAny<A, B> = __VLS_IsAny<A> extends true ? B : A;
23+
type __VLS_PrettifyGlobal<T> = { [K in keyof T as K]: T[K] } & {};
2224
declare function __VLS_asFunctionalComponent<
2325
T,
2426
K = T extends new (...args: any) => any ? InstanceType<T> : unknown,
2527
>(
2628
t: T,
27-
instance?: K,
2829
): T extends new (...args: any) => any
2930
? (
3031
props: (K extends { $props: infer Props }
@@ -35,27 +36,29 @@ declare function __VLS_asFunctionalComponent<
3536
ctx?: any,
3637
) => JSX.Element & {
3738
__ctx: {
38-
attrs?: Record<string, any>,
39+
attrs: Record<string, any>,
3940
props: (K extends { $props: infer Props }
4041
? Props
4142
: K extends { props: infer Props }
4243
? Props
4344
: any),
44-
slots?: K extends { $slots: infer Slots }
45+
slots: K extends { $slots: infer Slots }
4546
? Slots
4647
: K extends { slots: infer Slots }
4748
? Slots
4849
: any
49-
emit?: K extends { $emit: infer Emit }
50+
emit: K extends { $emit: infer Emit }
5051
? Emit
5152
: K extends { emit: infer Emit }
5253
? Emit
5354
: any
54-
exposed: K extends { exposed: infer Exposed }
55-
? keyof NonNullable<Exposed> extends never
56-
? K
57-
: import('vue').ShallowUnwrapRef<Exposed>
58-
: K
55+
expose: (
56+
exposed: K extends { exposeProxy: infer Exposed }
57+
? string extends keyof NonNullable<Exposed>
58+
? K
59+
: Exposed
60+
: K,
61+
) => void
5962
}
6063
}
6164
: T extends () => any
@@ -82,7 +85,15 @@ declare function __VLS_getFunctionalComponentCtx<T, K, const S>(
8285
? { expose: (exposed: (typeof __VLS_nativeElements)[S]) => any }
8386
: '__ctx' extends keyof __VLS_PickNotAny<K, {}>
8487
? K extends { __ctx?: infer Ctx } ? Ctx : never
85-
: T extends (props: infer P, ctx: infer Ctx) => any ? { props: P } & Ctx
88+
: T extends (props: infer P, ctx: { expose: (exposed: infer Exposed) => void } & infer Ctx) => any
89+
? Ctx & {
90+
props: P,
91+
expose: (
92+
exposed: __VLS_PrettifyGlobal<
93+
import('vue').ShallowUnwrapRef<Exposed>
94+
>,
95+
) => void,
96+
}
8697
: {};\n`)
8798
}
8899

packages/volar/src/jsx-directive/v-on.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ type __VLS_NormalizeEmits<T> = __VLS_PrettifyGlobal<
3939
[K in keyof T]: T[K] extends any[] ? { (...args: T[K]): void } : never
4040
}
4141
>
42-
>;
43-
type __VLS_PrettifyGlobal<T> = { [K in keyof T as K]: T[K]; } & {};\n`)
42+
>;\n`)
4443
}
4544

4645
export function transformOnWithModifiers(

packages/volar/src/jsx-ref.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function transformRef({
2222
codes.replaceRange(
2323
initializer.expression.end,
2424
initializer.expression.end,
25-
`<Parameters<NonNullable<typeof __VLS_ctx_${name.text}['expose']>>[0] | null>`,
25+
`<Parameters<typeof __VLS_ctx_${name.text}['expose']>[0] | null>`,
2626
)
2727
}
2828
}

playground/vue3/src/examples/jsx-ref/index.vue

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="tsx">
22
import { expectTypeOf } from 'expect-type'
3-
import { defineComponent } from 'vue'
3+
import { defineComponent, ref, type Ref } from 'vue'
44
import { useRef } from 'vue-macros/runtime'
55
import Comp from './comp.vue'
66
@@ -10,9 +10,20 @@ const Comp1 = defineComponent({
1010
},
1111
})
1212
13+
const VaporComp = (
14+
_: any,
15+
{ expose }: { expose: (exposed: { foo: Ref<number> }) => void },
16+
) => {
17+
expose({
18+
foo: ref(1),
19+
})
20+
return <div />
21+
}
22+
1323
const comp = useRef()
1424
let comp1 = $(useRef())
1525
const comp2 = $(useRef())
26+
const vaporCompRef = useRef()
1627
1728
defineRender(
1829
<>
@@ -24,6 +35,9 @@ defineRender(
2435
2536
<a ref={$$(comp2)} />
2637
{expectTypeOf<[HTMLAnchorElement | null | undefined]>([comp2])}
38+
39+
<VaporComp ref={vaporCompRef} />
40+
{expectTypeOf<number | null | undefined>(vaporCompRef.value?.foo)}
2741
</>,
2842
)
2943
</script>

0 commit comments

Comments
 (0)