Невозможно использовать атрибуты HTML на пользовательских компонентах в TSX - PullRequest
0 голосов
/ 24 октября 2018

Для начала, я использую 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>
    );
  }
});

1 Ответ

0 голосов
/ 27 октября 2018

Мне удалось отключить проверку типов атрибутов JSX, добавив следующее к namespace JSX в jsx.d.ts:

type LibraryManagedAttributes<C, P> = {[name: string]: any};

(По причинам, которые я не исследовал, type LibraryManagedAttributes<C, P> = any; не работает.)

Чтобы получить правильную проверку типа, нужно задать JSX.LibraryManagedAttributes для вычисления типа атрибутов JSX компонента из типа компонента.Но этот комментарий предполагает, что расчет очень сложен для Vue (в отличие от React).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...