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

jsx onClick is not assignable to type of .vue (custom component) #555

Open
icuxika opened this issue Apr 21, 2022 · 8 comments
Open

jsx onClick is not assignable to type of .vue (custom component) #555

icuxika opened this issue Apr 21, 2022 · 8 comments

Comments

@icuxika
Copy link

icuxika commented Apr 21, 2022

VButton

<script setup lang="ts">
import { computed } from "vue";

interface Props {
	theme?: string;
	size?: string;
	level?: string;
	disabled?: boolean;
	loading?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
	theme: "button",
	size: "normal",
	level: "normal",
	disabled: false,
	loading: false,
});

const classes = computed(() => {
	return {
		[`v3-theme-${props.theme}`]: props.theme,
		[`v3-size-${props.size}`]: props.size,
		[`v3-level-${props.level}`]: props.level,
	};
});
</script>
<template>
	<button class="v3-button" :class="classes" :disabled="props.disabled">
		<span v-if="props.loading" class="v3-loading-indicator"></span>
		<span v-else class="v3-loading-indicator-empty"></span>
		<slot />
	</button>
</template>

use VButton

export const DemoX = defineComponent({
	props: {
		component: {
			type: Object as PropType<Component>,
			required: true,
		},
	},
	setup(props, { attrs, slots, emit, expose }) {
		// 渲染源码
		const html = computed(() => {
			return Prism.highlight(
				(props.component as ComponentType).__sourceCode,
				Prism.languages.html,
				"html"
			);
		});
		// 源码是否可见
		const codeVisible = ref(false);
		const toggleCodeVisible = () =>
			(codeVisible.value = !codeVisible.value);
		return () => (
			<div class={style.container}>
				<h2>{(props.component as ComponentType).__sourceCodeTitle}</h2>
				<div class={style.component}>{h(props.component)}</div>
				<div class={style.action}>
						<VButton onClick={withModifiers(toggleCodeVisible, ["self"])}>
							{codeVisible.value ? "隐藏源代码" : "查看源代码"}
						</VButton>
				</div>
				{codeVisible.value ? (
					<div class={style.code}>
						<pre class={"language-html"} innerHTML={html.value} />
					</div>
				) : (
					<div />
				)}
			</div>
		);
	},
});

Question

It works normally when I use yarn dev, but it will report error when I use vue-tsc --noEmit && vite build

error TS2322: Type '{ onClick: (event: Event, ...args: unknown[]) => any; }' is not assignable to type 'IntrinsicAttributes & Partial<{ loading: boolean; disabled: boolean; size: string; theme: string; level: string; }> & Omit<Readonly<ExtractPropTypes<{ theme: { type: PropType<string>; } & { ...; }; size: { ...; } & { ...; }; level: { ...; } & { ...; }; disabled: { ...; } & { ...; }; loading: { ...; } & { ...; }; }>>...'.
  Property 'onClick' does not exist on type 'IntrinsicAttributes & Partial<{ loading: boolean; disabled: boolean; size: string; theme: string; level: string; }> & Omit<Readonly<ExtractPropTypes<{ theme: { type: PropType<string>; } & { ...; }; size: { ...; } & { ...; }; level: { ...; } & { ...; }; disabled: { ...; } & { ...; }; loading: { ...; } & { ...; }; }>>...'.

56       <VButton onClick={withModifiers(toggleCodeVisible, ["self"])}>
                  ~~~~~~~
error Command failed with exit code 2.
@icuxika
Copy link
Author

icuxika commented Apr 21, 2022

I temporarily avoided this problem by wrapping a layer of div and setting the click event to the div.

<div onClick={withModifiers(toggleCodeVisible, ["stop"])}>
	<VButton>
		{codeVisible.value ? "隐藏源代码" : "查看源代码"}
	</VButton>
</div>

Should I add an onClick prop to the VButton to solve this problem more rationally?

@funny-family
Copy link

funny-family commented Apr 21, 2022

@icuxika here is component example. Hope it will help you. If you have any questions, you are free to ask. 🙃

@funny-family
Copy link

@icuxika, you did not provide $attrs

<template>
	<button class="v3-button" :class="classes" :disabled="props.disabled" v-bind="$attrs">
		<span v-if="props.loading" class="v3-loading-indicator"></span>
		<span v-else class="v3-loading-indicator-empty"></span>
		<slot />
	</button>
</template>

Also I dont know if .tsx file will catch all component types that come from .vue component.

@icuxika
Copy link
Author

icuxika commented May 18, 2022

@funny-family Thanks, As a component in the library, I directly used this button by import the .vue and encountered this problem. Today I saw your new answer and try to delete the div, but there are some changes, which I didn't import like before, firstly I registered the component by app.component, then I found that vue-tsc can work normally without reporting error when $attrs has not been provided. It seems to be some details I don't know yet. Thanks again!

icuxika added a commit to icuxika/vue-scaffold-ui that referenced this issue May 18, 2022
@funny-family
Copy link

@icuxika, I still recommend you to take a lot at example of component. And yes, as you mentioned, vue3 and jsx have "some details", but in reality it has "a lot" of details.

Always glad to help 🙂

@icuxika
Copy link
Author

icuxika commented May 18, 2022

@icuxika Thank you for your advice. I will try to learn everything about example.

@mockingjet
Copy link

mockingjet commented Jun 9, 2023

image
Type '{ onClick: () => boolean; }' is not assignable to type 'IntrinsicAttributes & Partial ...

Manually adding HTMLAttributes to merge into Props is a bit burdensome. It requires a lot of boilerplate code to satisfy a basic need.

Using v-bind="$attrs" is not working. I add defineEmits(['click']); and <button @click="$emit('click')" /> as a temporary workaround. (although it is not a good one)

Looking forward to future updates.

@icuxika
Copy link
Author

icuxika commented Jun 9, 2023

@mockingjet I avoided this by using the global registration of the Vue component, but the TypeScript attribute hint for is incorrect in the .tsx file, even though there are no errors, and using in the .vue file, everything works as expected.

https://github.com/icuxika/vue-scaffold-ui/blob/main/src/main.ts

import {
	create as createVUI,
	VBanner,
	VButton,
	VMarkdown,
	VVerification,
	VConfigProvider,
} from "@icuxika/vue-scaffold-ui";

const vueScaffoldUI = createVUI({
	components: [VBanner, VButton, VMarkdown, VVerification, VConfigProvider],
});

https://github.com/icuxika/vue-scaffold-ui/blob/main/lib/create.ts

const create = ({
	components = [],
	componentPrefix = "V",
}: VCreateOption): VInstance => {
	const registerComponent = (
		app: App,
		name: string,
		component: Component
	) => {
		const registered = app.component(componentPrefix + name);
		if (!registered) {
			app.component(componentPrefix + name, component);
		}
	};

	const install = (app: App) => {
		components.forEach((component) => {
			registerComponent(app, component.name ?? "", component);
		});
	};

	return {
		install,
	};
};

https://github.com/icuxika/vue-scaffold-ui/blob/main/lib/button/Button.vue

<template>
	<button class="v3-button" :class="classes" :disabled="props.disabled">
		<span v-if="props.loading" class="v3-loading-indicator"></span>
		<span v-else class="v3-loading-indicator-empty"></span>
		<slot />
	</button>
</template>

https://github.com/icuxika/vue-scaffold-ui/blob/main/src/views/components/DemoX.tsx

return () => (
			<div class={style.container}>
				<h2>{(props.component as ComponentType).__sourceCodeTitle}</h2>
				<div class={style.component}>{h(props.component)}</div>
				<div class={style.action}>
					<v-button
						onClick={withModifiers(toggleCodeVisible, ["stop"])}
					>
						{codeVisible.value ? "隐藏源代码" : "查看源代码"}
					</v-button>
				</div>
				{codeVisible.value ? (
					<div class={style.code}>
						<pre class={"language-html"} innerHTML={html.value} />
					</div>
				) : (
					<div />
				)}
			</div>
		);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants