Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(language-core): correctly infer union props to options #4908

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions packages/language-core/lib/codegen/globalTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,26 @@ export function generateGlobalTypes(lib: string, target: number, strictTemplates
'__ctx' extends keyof __VLS_PickNotAny<K, {}> ? K extends { __ctx?: infer Ctx } ? Ctx : never : any
, T extends (props: any, ctx: infer Ctx) => any ? Ctx : any
>>;
type __VLS_IsUnion<T, U = T> = T extends U ? [U] extends [T] ? false : true : false;
type __VLS_InferUnionType<T, U, K> = K extends keyof T ? T[K] : K extends keyof U ? U[K] : never;
type __VLS_UnionKeys<T> = T extends any ? keyof T : never;
type __VLS_UnionRequiredKeys<T, K = __VLS_UnionKeys<T>> = Exclude<K, __VLS_UnionOptionalKeys<T>>;
type __VLS_UnionOptionalKeys<T, K = __VLS_UnionKeys<T>> = T extends any
? K extends keyof T
? {} extends Pick<T, K>
? K
: never
: never
: never;
type __VLS_MergeUnion<T, U = T> = T extends any
? { [V in __VLS_UnionRequiredKeys<U>]: __VLS_InferUnionType<T, U, V> }
& { [V in __VLS_UnionOptionalKeys<U>]?: __VLS_InferUnionType<T, U, V> }
: never;
type __VLS_PrettifyUnion<T> = {
[K in __VLS_UnionRequiredKeys<T>]: T[K]
} & {
[K in __VLS_UnionOptionalKeys<T>]?: T[K]
};

function __VLS_getVForSourceType(source: number): [number, number, number][];
function __VLS_getVForSourceType(source: string): [string, number, number][];
Expand Down
21 changes: 7 additions & 14 deletions packages/language-core/lib/codegen/localTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,13 @@ type __VLS_PropsChildren<S> = {
);
const TypePropsToOption = defineHelper(
`__VLS_TypePropsToOption`,
() => compilerOptions.exactOptionalPropertyTypes ?
`
type __VLS_TypePropsToOption<T> = {
[K in keyof T]-?: {} extends Pick<T, K>
? { type: import('${vueCompilerOptions.lib}').PropType<T[K]> }
: { type: import('${vueCompilerOptions.lib}').PropType<T[K]>, required: true }
};
`.trimStart() :
`
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
type __VLS_TypePropsToOption<T> = {
[K in keyof T]-?: {} extends Pick<T, K>
? { type: import('${vueCompilerOptions.lib}').PropType<__VLS_NonUndefinedable<T[K]>> }
: { type: import('${vueCompilerOptions.lib}').PropType<T[K]>, required: true }
() => `
${compilerOptions.exactOptionalPropertyTypes ? '' : 'type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;'}
type __VLS_TypePropsToOption<T, U = __VLS_IsUnion<T> extends true ? __VLS_PrettifyUnion<__VLS_MergeUnion<T>> : T> = {
[K in keyof U]-?: {
type: import('${vueCompilerOptions.lib}').PropType<${compilerOptions.exactOptionalPropertyTypes ? 'U[K]' : '__VLS_NonUndefinedable<U[K]>'}>,
required: {} extends Pick<U, K> ? false : true
}
};
`.trimStart()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ export function* generateElementEvents(
}
yield `(${newLine}`;
yield `__VLS_IsFunction<typeof ${propsVar}, '${originalPropName}'> extends true${newLine}`;
yield `? typeof ${propsVar}${newLine}`;
yield `? {${newLine}`;
yield `${originalPropNameObjectKey}?: typeof ${propsVar}['${originalPropName}']${newLine}`;
yield `}${newLine}`;
yield `: __VLS_IsFunction<typeof ${eventsVar}, '${prop.arg.loc.source}'> extends true${newLine}`;
yield `? {${newLine}`;
yield `/**__VLS_emit,${emitVar},${prop.arg.loc.source}*/${newLine}`;
Expand Down
28 changes: 12 additions & 16 deletions packages/tsc/tests/__snapshots__/dts.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -328,34 +328,32 @@ exports[`vue-tsc-dts > Input: reference-type-model/component.vue, Output: refere
"qux"?: string;
quxModifiers?: Record<'lazy' | 'trim', true>;
};
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<__VLS_PublicProps>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<__VLS_PublicProps, __VLS_PublicProps>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
"update:foo": (foo: number) => void;
"update:bar": (bar: string[]) => void;
"update:qux": (qux: string) => void;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<__VLS_PublicProps>>> & Readonly<{
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<__VLS_PublicProps, __VLS_PublicProps>>> & Readonly<{
"onUpdate:foo"?: (foo: number) => any;
"onUpdate:bar"?: (bar: string[]) => any;
"onUpdate:qux"?: (qux: string) => any;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
export default _default;
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
type __VLS_TypePropsToOption<T> = {
[K in keyof T]-?: {} extends Pick<T, K> ? {
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
} : {
type: import('vue').PropType<T[K]>;
required: true;
type __VLS_TypePropsToOption<T, U = __VLS_IsUnion<T> extends true ? __VLS_PrettifyUnion<__VLS_MergeUnion<T>> : T> = {
[K in keyof U]-?: {
type: import('vue').PropType<__VLS_NonUndefinedable<U[K]>>;
required: {} extends Pick<U, K> ? false : true;
};
};
"
`;

exports[`vue-tsc-dts > Input: reference-type-props/component.vue, Output: reference-type-props/component.vue.d.ts 1`] = `
"import { MyProps } from './my-props';
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<MyProps>, {
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<MyProps, MyProps>, {
bar: number;
baz: () => string[];
}>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<MyProps>, {
}>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<MyProps, MyProps>, {
bar: number;
baz: () => string[];
}>>> & Readonly<{}>, {
Expand All @@ -369,12 +367,10 @@ type __VLS_WithDefaults<P, D> = {
}> : P[K];
};
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
type __VLS_TypePropsToOption<T> = {
[K in keyof T]-?: {} extends Pick<T, K> ? {
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
} : {
type: import('vue').PropType<T[K]>;
required: true;
type __VLS_TypePropsToOption<T, U = __VLS_IsUnion<T> extends true ? __VLS_PrettifyUnion<__VLS_MergeUnion<T>> : T> = {
[K in keyof U]-?: {
type: import('vue').PropType<__VLS_NonUndefinedable<U[K]>>;
required: {} extends Pick<U, K> ? false : true;
};
};
type __VLS_PrettifyLocal<T> = {
Expand Down
1 change: 1 addition & 0 deletions test-workspace/tsc/passedFixtures/vue2/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"../vue3/#4649",
"../vue3/#4777",
"../vue3/#4820",
"../vue3/core#12110",
"../vue3/components",
"../vue3/defineEmits",
"../vue3/defineModel",
Expand Down
1 change: 1 addition & 0 deletions test-workspace/tsc/passedFixtures/vue3.4/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"../vue3/#3820",
"../vue3/#4777",
"../vue3/#4820",
"../vue3/core#12110",
"../vue3/rootEl",
"../vue3/templateRef",
"../vue3/templateRef_native",
Expand Down
16 changes: 16 additions & 0 deletions test-workspace/tsc/passedFixtures/vue3/core#12110/comp.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script setup lang="ts">
type Props = {
foo: string;
} | {
foo?: boolean;
bar: string;
};

withDefaults(defineProps<Props>(), {
foo: true
});

defineEmits<{
click: [e: number]
}>();
</script>
9 changes: 9 additions & 0 deletions test-workspace/tsc/passedFixtures/vue3/core#12110/main.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script setup lang="ts">
import Comp from './comp.vue';
import { exactType } from '../../shared';
</script>

<template>
<Comp foo="..." @click="(e) => exactType(e, {} as number)" />
<Comp bar="..." @click="(e) => exactType(e, {} as number)" />
</template>