Для начала, я использую jsx: "preserve"
с этим jsx.d.ts
файлом, взятым из быстрого поиска Google по теме.
import Vue, {VNode} from "vue";
declare global {
namespace JSX {
interface Element extends VNode {}
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any;
}
}
}
К сожалению, в то время как все, что я нашел, в значительной степени обеспечивало этот точныйВ файле объявления ни один из результатов не углубился в то, как использовать JSX с пользовательскими компонентами.
В моем случае у меня есть компонент, определенный с Vue.extend()
, который я хотел бы использовать в JSX.Этот компонент является экспортом по умолчанию в файл с именем SomeComponent.tsx
.Код, вызывающий проблему, выглядит следующим образом.
import Vue, {CreateElement} from "vue";
import SomeComponent from "./SomeComponent.tsx";
export default Vue.extend({
name: "SomeOtherComponent",
functional: true,
render: (h: CreateElement) => (
<div class="something">
<SomeComponent
class="something-else"
someProp={1234}
>
Slot Content
</SomeComponent>
</div>
)
});
Ошибка компиляции в строке 11, столбце 9 со следующим сообщением: TS2339: Property 'class' does not exist on type 'ComponentOptions<Record<string, any> & Vue, DefaultData<Record<string, any> & Vue>, DefaultMethod...'
.
Я понимаю, что не удается набратьпроверьте использование class="something-else"
в пользовательском компоненте.
Взято из предложения JSX в TypeScript для GitHub:
<Something x={expr1} { ...spr } y={expr2} />
С учетом атрибутов элементатип E
, полученный из Something
в приведенном выше примере, атрибуты элемента проверяются следующим образом:
Если атрибут является обычным атрибутом P
, инициализированным expr
:
ЕслиE
имеет свойство P
, процесс expr
с контекстным типом типа E.P
.В противном случае выдайте ошибку.
Это ошибка, если expr
нельзя присвоить E.P
.
Однако я не знаю / не понимаю, как я будувозможность получить атрибут class
для проверки типов должным образом, т. е. каким образом мне нужно настроить мой jsx.d.ts
.
Если потребуется, мне также будет достаточно отключить проверку типов дляJSX, но я не уверен, как бы я это сделал.Вот что я попробовал до сих пор.
Согласно предложению, связанному выше
Если тип элемента any
, тип экземпляра элемента any
.
Я попытался установить JSX.ElementClass
в any
, заменив interface ElementClass extends Vue {}
на type ElementClass = any
, но не удалось с той же ошибкой в том же месте.
Я также попытался добавить interface ElementAttributesPropert {}
к моему jsx.d.ts
, в соответствии с
Интерфейс JSX.ElementAttributesProperty
определяет этот процесс.Он может иметь 0 свойств, и в этом случае все атрибуты считаются действительными и имеют тип any
, [...].
Это, в свою очередь, приводит к другой ошибке, то есть
TS2322: Type '{ class: string; someProp: number; }' is not assignable to type 'CombinedVueInstance<Record<string, any> & Vue, object, object, object, Record<never, any>>'.
Type '{ class: string; someProp: number; }' is not assignable to type 'Vue'.
Property '$el' is missing in type '{ class: string; someProp: number; }'.
Я знаю, что этот код должен работать, так как я запускал его через Babel после ручного удаления частей TypeScript и получения ожидаемого вывода.
Редактировать для MattМаккатчен:
Это определение для SomeComponent
У меня есть.Это просто оболочка вокруг <router-link />
, чтобы сделать что-то дополнительное при нажатии.Работает как шарм в обычных шаблонах, например, SFC <template>
.Единственная причина, по которой я пытался решить эту проблему с помощью JSX, была эта проблема с шаблонами и функциональными компонентами.
import Vue, {CreateElement, RenderContext} from "vue";
export default Vue.extend({
name: "SomeComponent",
functional: true,
render(h: CreateElement, {children, data}: RenderContext) {
const doStuff = () => console.log("Hello there!");
return (
<router-link
{...data}
nativeOnClick={doStuff}
>
{children}
</router-link>
);
}
});