TSX (JSX for TypeScript) support library for Vue

Overview

npm version build

vue-tsx-support

TSX (JSX for TypeScript) support library for Vue

⚠️ BREAKING CHANGES

If your project already uses vue-tsx-support v2, see Migration from V2 section.

TABLE OF CONTENTS

NEW FEATURES

  • Typesafe emit for declared events
  • @vue/composition-api support

PREREQUISITE

  • Vue >= 2.6.0, < 3.0.0

  • TypeScript >= 3.8.0 (3.9.2 or later recommended)

    vue-tsx-support does not support Vue 3 because Vue 3 has it's own JSX type checker and there are some incompatibilities with Vue 2.

    If you want to use composition API with vue-tsx-support, you can use @vue/composition-api.

INSTALLATION

  1. Create Vue project with TypeScript and babel support.

    vue-tsx-support is a type checker for TypeScript, not a transpiler.
    You must install babel presets (@vue/babel-preset-app or @vue/babel-preset-jsx) separatedly.

    Vue CLI may help you.

    💡 If you want use @vue/composition-api, @vue/babel-preset-jsx >= 1.2.1 or babel-preset-vue-vca is needed.

  2. Install vue-tsx-support from npm

    yarn add vue-tsx-support -D
    
  3. In tsconfig.json, set "preserve" to jsx and "VueTsxSupport" to jsxFactory

    {
      "compilerOptions": {
        "jsx": "preserve",
        "jsxFactory": "VueTsxSupport",
        "...": "..."
      },
      "include": [
        "..."
      ]
    }
  4. import vue-tsx-support/enable-check.d.ts somewhere,

    import "vue-tsx-support/enable-check"

    or add it to "include" in tsconfig.json

    {
      "compilerOptions": {
        "...": "..."
      },
      "include": [
        "node_modules/vue-tsx-support/enable-check.d.ts",
        "..."
      ]
    }

Migration from V2

  1. In tsconfig.json, set "VueTsxSupport" to jsxFactory

  2. Enable allow-props-object option (Optional)

USAGE

Intrinsic elements

Standard HTML elements are defined as intrinsic elements. So, compiler can check attribute names and attribute types of them:

// OK
<div id="title" />;
// OK
<input type="number" min={ 0 } max={ 100 } />;
// OK
<a href={ SOME_LINK } />;
// NG: because `href` is not a valid attribute of `div`
<div href={ SOME_LINK } />;
// NG: because `id` must be a string
<div id={ 1 } />;

Lower case tags are treated as unknown intrinsic element. TypeScript checks nothing for such tags.

// OK
<foo id="unknown" unknownattr={ 1 } />

Components

Basically, vue-tsx-support checks three types for each component.

  • Prop types
    Determine name, type, and required or optional of each props.
    When using existing component as-is, you must specify prop types manually.
    When writing component with APIs of vue-tsx-support, prop types are automatically obtained from component definition.

  • Custom event types (optional)
    If the component has custom events, you can specify custom event types additionally,
    and vue-tsx-support will check if event names and argument types are correct or not.

  • Scoped slot types (optional)
    If the component has uses scoped slots, you can specify scoped slot types additionally,
    and vue-tsx-support will check if scoped slot names and argument types are correct or not.

Make existing components tsx-ready.

By default, vue-tsx-support does not allow unknown props.
For example, below code causes compilation error.

import Vue from "vue";
import AwesomeButton from "third-party-library/awesome-button";

export default Vue.extend({
  render() {
    // ERROR: because TypeScript does not know that AwesomeButton has 'text' prop.
    return <AwesomeButton text="Click Me!" />;
  }
});

You can add type information to existing component without modifying component itself, like below:

import AwesomeButtonOrig from "third-party-library/awesome-button";
import * as tsx from "vue-tsx-support";

type AwesomeButtonProps = {
  text: string;
  raised?: boolean;
  rounded?: boolean;
}

// Now, AwesomeButton has 1 required prop(text) and 2 optional props(raised, rounded)
export const AwesomeButton = tsx.ofType<AwesomeButtonProps>().convert(AwesomeButtonOrig);

You also can specify custom event types as second type parameter, and scoped slot types as third type parameter.

For example:

import AwesomeListOrig from "third-party-library/awesome-list";
import * as tsx from "vue-tsx-support";

type Item = { id: string, text: string };

type AwesomeListProps = {
  items: ReadonlyArray<Item>;
  rowHeight: number;
}

type AwesomeListEvents = {
  // member name must be ['on' + event name(with capitalizing first charactor)]
  onRowClicked: { item: Item, index: number };
}

type AwesomeListScopedSlots = {
  row: { item: Item }
}

export const AwesomeList = tsx.ofType<
  AwesomeListProps,
  AwesomeListEvents,
  AwesomeListScopedSlots
>().convert(AwesomeListOrig);

Then you can use AwesomeList like below:

import { VNode } from "vue";
const App = Vue.extend({
render(): VNode {
  return (
    <AwesomeList
      items={this.items}
      rowHeight={32}
      onRowClicked={p => console.log(`${p.item.text} clicked!`)}
      scopedSlots={{
        row: item => <div>{item.text}</div>
      }}
    />
  );
}
});

Writing components by object-style API (Like Vue.extend)

If you use Vue.extend(), just replace it by componentFactory.create and your component becomes TSX-ready.

Props type is infered from props definition automatically.
For example, props type will be { text: string, important?: boolean } in below code.

⚠️ In some environment, as const may be needed to make prop required properly.

import { VNode } from "vue";
import * as tsx from "vue-tsx-support";
const MyComponent = tsx.componentFactory.create({
  props: {
    text: { type: String, required: true },
    important: Boolean,
  } as const, // `as const` is needed in some cases.
  computed: {
    className(): string {
      return this.important ? "label-important" : "label-normal";
    }
  },
  methods: {
    onClick(event: Event) { this.$emit("ok", event); }
  },
  render(): VNode {
    return <span class={this.className} onClick={this.onClick}>{this.text}</span>;
  }
});

💡 You can use component as as shorthand of componentFactory.create.

import * as tsx from "vue-tsx-support";
const MyComponent = tsx.component({
  /* snip */
});

If your component has custom events or scoped slots, use componentFactoryOf instead.

import { VNode } from "vue";
import * as tsx from "vue-tsx-support";

type AwesomeListEvents = {
  onRowClicked: { item: {}, index: number };
}

type AwesomeListScopedSlots = {
  row: { item: {} }
}

export const AwesomeList = tsx.componentFactoryOf<
  AwesomeListEvents,
  AwesomListScopedSlots
>().create({
  name: "AwesomeList",
  props: {
    items: { type: Array, required: true },
    rowHeight: { type: Number, required: true }
  },
  computed: { /* ... */},
  method: {
    emitRowClicked(item: {}, index: number): void {
      // Equivalent to `this.$emit("rowClicked", { item, index })`,
      // And event name and payload type are statically checked.
      tsx.emitOn(this, "onRowClicked", { item, index });
    }
  },
  render(): VNode {
    return (
      <div class={style.container}>
        {
          this.visibleItems.map((item, index) => (
            <div style={this.rowStyle} onClick={() => this.$emit("rowClicked", { item, index })}>
              {
                // slot name ('row') and argument types are statically checked.
                this.$scopedSlots.row({ item })
              }
            <div>
          )
        }
      </div>
    );
  }
});

Writing component by class-style API (vue-class-component and/or vue-property-decorator)

If you prefer class-style component by using vue-class-component and/or vue-property-decorator, there are some options to make it tsx-ready.

1. Extends from Component class provided by vue-tsx-support
import { VNode } from "vue";
import { Component, Prop } from "vue-property-decorator";
import * as tsx from "vue-tsx-support";

type MyComponentProps = {
  text: string;
  important?: boolean;
}

@Component
export class MyComponent extends tsx.Component<MyComponentProps> {
  @Prop({ type: String, required: true })
  text!: string;
  @Prop(Boolean)
  important?: boolean;

  get className() {
    return this.important ? "label-important" : "label-normal";
  }
  onClick(event: MouseEvent) {
    this.$emit("ok", event);
  }
  render(): VNode {
    return <span class={this.className} onClick={this.onClick}>{this.text}</span>;
  }
}

⚠️ Unfortunately, vue-tsx-support can't infer prop types automatically in this case, so you must write type manually.

2. Add _tsx field to tell type information to TypeScript.
import { VNode } from "vue";
import { Component, Prop } from "vue-property-decorator";
import * as tsx from "vue-tsx-support";

@Component
export class MyComponent extends Vue {
  _tsx!: {
    // specify props type to `props`.
    props: Pick<MyComponent, "text" | "important">
  };

  @Prop({ type: String, required: true })
  text!: string;
  @Prop(Boolean)
  important?: boolean;

  get className() {
    return this.important ? "label-important" : "label-normal";
  }
  render(): VNode {
    return <span class={this.className}>{this.text}</span>;
  }
}

You can use DeclareProps<T> instead of { props: T }.

import { Component, Prop } from "vue-property-decorator";
import * as tsx from "vue-tsx-support";

@Component
export class MyComponent extends Vue {
  _tsx!: tsx.DeclareProps<Pick<MyComponent, "text" | "important">>;

  /* ...snip... */
}

💡 PickProps is more convenient than Pick here, it removes attributes from Vue from completion candidates. (e.g. $data, $props, and so on)

import { Component, Prop } from "vue-property-decorator";
import * as tsx from "vue-tsx-support";

@Component
export class MyComponent extends Vue {
  _tsx!: tsx.DeclareProps<tsx.PickProps<MyComponent, "text" | "important">>;

  /* ...snip... */
}

💡 When you can make all data, computed and methods private, you can use AutoProps instead.
AutoProps picks all public members other than members from component options(render, created etc).

import { Component, Prop } from "vue-property-decorator";
import * as tsx from "vue-tsx-support";

@Component
export class MyComponent extends Vue {
  _tsx!: tsx.DeclareProps<tsx.AutoProps<MyComponent>>

  @Prop({ type: String, required: true })
  text!: string;

  @Prop(Boolean)
  important?: boolean;

  // data
  private count = 0;
  // computed
  private get className() {
    return this.important ? "label-important" : "label-normal";
  }
  // methods
  private onClick() {
    this.count += 1;
  }

  render(): VNode {
    return (
      <span class={this.className} onClick={this.onClick}>
        {`${this.text}-${this.count}`}
      </span>
    );
  }
}

💡 If your component has custom events, you can specify events handlers type additionally.

import { Component, Prop } from "vue-property-decorator";
import * as tsx from "vue-tsx-support";

@Component
export class MyComponent extends Vue {
  _tsx!: tsx.DeclareProps<PickProps<MyComponent, "text" | "important">> &
    tsx.DeclareOnEvents<{ onOk: string }>;

  /* ...snip... */
}

💡 If your component uses scoped slots, you should add type to $scopedSlots by tsx.InnerScopedSlots.

import { Component, Prop } from "vue-property-decorator";
import * as tsx from "vue-tsx-support";

@Component
export class MyComponent extends Vue {
  _tsx!: tsx.DeclareProps<PickProps<MyComponent, "text" | "important">>;

  $scopedSlots!: tsx.InnerScopedSlots<{ default?: string }>;

  /* ...snip... */
}

Writing component by composition api (@vue/composition-api)

Vue 3 is not supported. To use composition api with Vue 2, You can use @vue/composition-api.

There are 2 babel presets which support JSX syntax with @vue/composition-api.

  • @vue/babel-preset-jsx >= 1.2.1 (You must enable composition-api support explicitly by specifying { compositionAPI: true })
  • babel-preset-vca-jsx

To make TSX-ready component by composition api, use component of vue-tsx-support/lib/vca instead of defineComponent of @vue/composition-api.

import { computed } from "@vue/composition-api";
import * as vca from "vue-tsx-support/lib/vca";

const MyComponent = vca.component({
  name: "MyComponent",
  props: {
    text: { type: String, required: true },
    important: Boolean,
  },
  setup(p) {
    const className = computed(() => p.important ? "label-important" : "label-normal");
    return () => (
      <span class={className.value}>{p.text}</span>;
    );
  }
});

If your component has custom event or scoped slots, specify them types in 2nd argument of setup.

import { computed, onMounted } from "@vue/composition-api";
import * as vca from "vue-tsx-support/lib/vca";

type AwesomeListEvents = {
  onRowClicked: { item: {}, index: number };
}

type AwesomeListScopedSlots = {
  row: { item: {} }
}

export const AwesomeList = vca.component({
  name: "AwesomeList",
  props: {
    items: { type: Array, required: true },
    rowHeight: { type: Number, required: true }
  },
  setup(p, ctx: vca.SetupContext<AwesomeListEvents, AwesomeListScopedSlots>) {
    const visibleItems = computed(() => ... );
    const emitRowClicked = (item: {}, index: number) => {
      // Equivalent to `ctx.emit("rowClicked", { item, index })`,
      // And event name and payload type are statically checked.
      vca.emitOn(ctx, "onRowClicked", { item, index });
    }

    return () => (
      <div class={style.container}>
        {
          visibleItems.value.map((item, index) => (
            <div onClick={() => emitRowClicked(item, index)}>
              {
                // slot name ('row') and argument types are statically checked.
                ctx.slots.row({ item })
              }
            <div>
          )
        }
      </div>
    );
  }
});

OPTIONS

vue-tsx-support has some options which change behaviour globally. See under the options directory.

To enable each options, import them somewhere

// enable `allow-unknown-props` option
import "vue-tsx-support/options/allow-unknown-props";

⚠️ Scope of option is whole project, not a file.

allow-element-unknown-attrs

Make enabled to specify unknown attributes to intrinsic elements

// OK:`foo` is unknown attribute, but can be compiled
<div foo="foo" />;

allow-unknown-props

Make enabled to specify unknown props to Vue component.

const MyComponent = vuetsx.createComponent<{ foo: string }>({ /* ... */ });
// OK: `bar` is unknown prop, but can be compiled
<MyComponent foo="foo" bar="bar" />;

enable-html-attrs

Make enabled to specify HTML attributes to Vue component.

const MyComponent = vuetsx.createComponent<{ foo: string }>({ /* ... */ });
// OK: `min` and `max` are valid HTML attributes
<MyComponent foo="foo" min={ 0 } max={ 100 } />;
// NG: compiler checks type of `min` (`min` must be number)
<MyComponent foo="foo" min="a" />;

enable-nativeon

Make enabled to specify native event listeners to Vue component.

const MyComponent = vuetsx.createComponent<{ foo: string }>({ /* ... */ });
// OK
<MyComponent foo="foo" nativeOnClick={ e => ... } />; // and `e` is infered as MouseEvent

enable-vue-router

Add definitions of router-link and router-view

allow-props-object

Make enabled to pass props as "props".

const MyComponent = vuetsx.createComponent<{ foo: string }>({ /* ... */ });
// OK
<MyComponent props={{ foo: "foo" }} />;

APIS

modifiers

Event handler wrappers which work like some event modifiers available in template

import { modifiers as m } from "vue-tsx-support";

// Basic usage:
//  Equivalent to `<div @keydown.enter="onEnter" />`
<div onKeydown={m.enter(this.onEnter)} />;

// Use multiple modifiers:
//  Equivalent to `<div @keydown.enter.prevent="onEnter" />`
<div onKeydown={m.enter.prevent(this.onEnter)} />;

// Use without event handler:
//  Equivalent to `<div @keydown.esc.prevent />`
<div onKeydown={m.esc.prevent} />;

// Use multiple keys:
//  Equivalent to `<div @keydown.enter.esc="onEnterOrEsc" />`
<div onKeydown={m.keys("enter", "esc")(this.onEnterOrEsc)} />;

// Use exact modkey combination:
//  Equivalent to `<div @keydown.65.ctrl.alt.exact="onCtrlAltA" />`
<div onKeydown={m.keys(65).exact("ctrl", "alt")(this.onCtrlAltA)} />;

Available modifiers

  • esc, tab, enter, space, up, down, del, left, right

    Execute event handler only when specified key is pressed.
    ⚠️ del allows not only DELETE, but also BACKSPACE.
    ⚠️ left and right have another behavior when specified to mouse event
    ⚠️ combination of key modifiers (e.g. m.enter.esc) does not work. See keys

  • left, right, middle

    Execute event handler only when specified mouse button is pressed.
    ⚠️ left and right have another behavior when specified to keyboard event

  • ctrl, shift, alt, meta

    Execute event handler only when specified system modifier key is pressed.

  • noctrl, noshift, noalt, nometa

    Execute event handler only when specified system modifier key is not pressed.

  • self

    Execute event handler only when event.target is the element itself (not from children).

  • prevent, stop

    Call preventDefault or stopPropagation of event object before executing event handler.

  • keys(...args)

    Execute event handler only when one of specified key is pressed.
    Known key name("esc", "tab", "enter", ...) or number can be specified.

    // when enter or esc pressed
    <div onKeydown={m.keys("enter", "esc")(handler)} />;
    // when 'a' pressed
    <div onKeydown={m.keys(65)(handler)} />;
  • exact(...args)

    Execute event handler only when specified system modifier keys are all pressed, and others are not pressed.

    // when CTRL, SHIFT are both pressed, and ALT, META are both not pressed
    <div onClick={m.exact("ctrl", "shift")(handler)} />;

LICENSE

MIT

Comments
  • [Bug] Object literal may only specify known properties, and 'data' does not exist in type 'FunctionalComponentOptions<unknown, RecordPropsDefinition<unknown>>'.

    [Bug] Object literal may only specify known properties, and 'data' does not exist in type 'FunctionalComponentOptions>'.

    Example

    import * as tsx from "vue-tsx-support";
    const MyComponent = tsx.componentFactory.create({
    +  data() {
    +   return {
    +      a: 1,
    +   }
    +  },
      props: {
        text: { type: String, required: true },
        important: Boolean,
      } as const, // `as const` is needed in some cases.
      computed: {
        className(): string {
          return this.important ? "label-important" : "label-normal";
        }
      },
      methods: {
        onClick(event) { this.$emit("ok", event); }
      },
      render(): VNode {
        return <span class={this.className} onClick={this.onClick}>{this.text}</span>;
      }
    });
    

    Error

    TS2769: No overload matches this call. friendly-errors 16:40:09 Overload 1 of 2, '(options: FunctionalComponentOptions<unknown, RecordPropsDefinition>, requiredProps?: never[] | undefined): _TsxComponentV3<Vue & { ...; }, ... 4 more ..., {}>', gave the following error. Argument of type '{ name: string; props: { value: { type: () => Status; required: boolean; }; readonly: { type: BooleanConstructor; default: boolean; }; }; data(this: CombinedVueInstance<Vue & { _tsx: TsxComponentTypeInfo<{}, {}, Events, {}>; $scopedSlots: InnerScopedSlots<...>; } & { ...; }, unknown, unknown, unknown, Readonly<...>>...' is not assignable to parameter of type 'FunctionalComponentOptions<unknown, RecordPropsDefinition>'. Object literal may only specify known properties, and 'data' does not exist in type 'FunctionalComponentOptions<unknown, RecordPropsDefinition>'. Overload 2 of 2, '(options: object & ComponentOptions<Vue & { _tsx: TsxComponentTypeInfo<{}, {}, Events, {}>; $scopedSlots: InnerScopedSlots<{}>; } & { _tsx: DeclareProps<{ ...; } & { ...; }>; }, ... 4 more ..., { ...; }> & ThisType<...> & { ...; }, requiredPropsNames?: ("value" | "readonly")[] | undefined): _TsxComponentV3<...>', gave the following error. Property '_tsx' is missing in type '{ value: { type: () => Status; required: true; }; readonly: { type: BooleanConstructor; default: false; }; }' but required in type 'RecordPropsDefinition<{ value: Status; readonly: boolean; _tsx: DeclareProps<{ value: Status; } & { readonly?: boolean | undefined; }>; }>'. 37 | }

    Information

    Temporarily work

    import * as tsx from "vue-tsx-support";
    const MyComponent = tsx.componentFactory.create({
    -  data() {
    -   return {
    -      a: 1,
    -   }
    -  },
    +  data: () => ({
    +   a: 1,
    +  }),
      props: {
        text: { type: String, required: true },
        important: Boolean,
      } as const, // `as const` is needed in some cases.
      computed: {
        className(): string {
          return this.important ? "label-important" : "label-normal";
        }
      },
      methods: {
        onClick(event) { this.$emit("ok", event); }
      },
      render(): VNode {
        return <span class={this.className} onClick={this.onClick}>{this.text}</span>;
      }
    });
    

    Version

    Work:<= v3.0.0-dev.6e Not Work:>= v3.0.0-dev.6e

    opened by gd4Ark 11
  • [bug] The dynamic element(tag) can not apply the onChange events to `on`.

    [bug] The dynamic element(tag) can not apply the onChange events to `on`.

    like this:

    const Tag = this.props.long ? "textarea" : "input"
    
    const input = <Tag 
      onChange={this.props.onChange}
      className="make-this-pretty"
      id="important-input"
    />;
    
    opened by snowyu 7
  • Mixins props is marked as required by typescript even tho I defined it as optional

    Mixins props is marked as required by typescript even tho I defined it as optional

    import PropTypes from 'vue-strict-prop';
    
    export const textXsCenterMixin = {
      props: {
        textXsCenter: PropTypes(Boolean).optional,
      },
    };
    
    
    const Flex = componentFactory.mixin(textXsCenterMixin).create({ //...
    

    image

    Typescript complain Property 'textXsCenter' is missing in type

    opened by chanlito 7
  • Jest and TSX are not working

    Jest and TSX are not working

    Please, see https://github.com/vuejs/vue-cli/issues/6389 for details. Related to #77 and https://github.com/wonderful-panda/vue-tsx-support/commit/175cdf9a8a26e4369e874472a45eb7f5524ade00

    In summary, we need CommonJS version. Workaround: add transformIgnorePatterns: [] to babel config

    A proper fix is to change the vue-tsx-support package to provide both CommonJS and ES module entries, following the guide from the Node.js documentation: https://nodejs.org/api/packages.html#packages_conditional_exports

    (c) @sodatea

    opened by Maxim-Mazurok 5
  • Convertion does not work properly

    Convertion does not work properly

            const ToolbarTyped = tsx.ofType<{ tools: ITool[] }>().convert(Toolbar);
            return (
                <div>
                    <ToolbarTyped tools={this.tools} />
                </div>);
    

    Error:(34, 18) TS2322: Type '{ tools: ITool[]; }' is not assignable to type 'ComponentOptions<{ _tsxattrs: TsxComponentAttrs<{ tools: ITool[]; }, {}, {}>; } & Toolbar, DefaultData<{ _tsxattrs: TsxComponentAttrs<{ tools: ITool[]; }, {}, {}>; } & Toolbar>, DefaultMethods<{ _tsxattrs: TsxComponentAttrs<...>; } & Toolbar>, DefaultComputed, PropsDefinition<...>, Record<...>>'. Property 'tools' does not exist on type 'ComponentOptions<{ _tsxattrs: TsxComponentAttrs<{ tools: ITool[]; }, {}, {}>; } & Toolbar, DefaultData<{ _tsxattrs: TsxComponentAttrs<{ tools: ITool[]; }, {}, {}>; } & Toolbar>, DefaultMethods<{ _tsxattrs: TsxComponentAttrs<...>; } & Toolbar>, DefaultComputed, PropsDefinition<...>, Record<...>>'.

    opened by eakarpov 5
  • [fix] scoped slot typing

    [fix] scoped slot typing

    • Update vue dependencies
    • Fix scoped slots definitions to be compatible with Vue typings
    • ScopedSlots can be undefined as there is no guarantee that the scoped slot has to be passed. https://github.com/vuejs/vue/commit/448ba65d2b139b29f1e6891add9925ac22ffe10b
    • Fixes #11
    opened by blake-newman 5
  • Make entries in  scopedSlots optional

    Make entries in scopedSlots optional

    With the current type definition TypeScript assumes that all scoped slots have to be provided. This makes it impossible to pass only one of multiple scoped slots.

    This PR adjusts scopedSlots type to allow passing one or more scoped slots.

    Before:

    Due to the current type definition TypeScript complains that some of the slots are missing. This means, according to TypeScript you always have to pass all scoped slots. It is impossible to pass only one or some of them.

    bildschirmfoto 2018-11-12 um 15 46 23

    After:

    ommiting some or all scoped slots is not an error anymore:

    bildschirmfoto 2018-11-12 um 15 48 58

    but passing some incompatible type still leads to an error message:

    bildschirmfoto 2018-11-12 um 15 50 30
    opened by thenickname 5
  • SSR not working in 3.1.0

    SSR not working in 3.1.0

    I use this package with nuxt.js. SSR not working because the output file type was changed from commonjs to es2015 in v3.1.0. (SyntaxError: Unexpected token 'export' error occurs on node.js)

    Are there any plans to support(build) both commonjs and esmodule?

    opened by Yama-Tomo 4
  • onFooBar will resolve to fooBar , not foo-bar as expected

    onFooBar will resolve to fooBar , not foo-bar as expected

    for example, I used el-pagination

    firstly, I created its types

    import { Pagination } from "element-ui"
    
    interface ElPaginationProps1 extends ElPaginationBaseProps {
      total: number;
    }
    interface ElPaginationProps2 extends ElPaginationBaseProps {
      pagerCount: number;
    }
    type ElPaginationProps = ElPaginationProps1 | ElPaginationProps2
    
    interface ElPaginationEvents {
      onSizeChange: number;
      onCurrentChange: number;
      onPrevClick: number;
      onNextClick: number;
    }
    export const ElPagination = tsx.ofType<ElPaginationProps, ElPaginationEvents>().convert(Pagination)
    
    

    then when I use it

    <ElPagination
            pageSize={1}
            currentPage={1}
            total={1}
            onCurrentChange={ num => console.log("hi") }
    ></ElPagination>
    

    Above code does not work as expected. in vue dev tools you can see the ElPagination instance's $listener only has one which so called "currentChange"

    In fact, I want listen the "current-change" event

    Maybe someone will say: why don't u use "on-current-change" instead. If so, we will lose the type check, ide would not know the variable num was number

    opened by alonesuperman 4
  • Generic prop types are not working (Type 'SomeType' is not assignable to type 'T')

    Generic prop types are not working (Type 'SomeType' is not assignable to type 'T')

    Hello,

    I have an issue when trying to create a vue component using a generic factory function. The problem is that the generic type never gets "resolved" to an actual type. It always stays T instead of becoming something useful like SomeType.

    To be honest I am not sure if this is a limitation in vue, vue-tsx-support or TypeScript itself. Maybe someone could help clarify the issue or see if this is an actual error?

    Here is what I am trying to do:

    // define a generic component factory function
    function myComponentFactory<T>() {
    
      return component( {
    
        name: 'MyComponent',
    
        render() {
          return (
            <ul>
            { this.options.map( ( el, i ) =>
                <li key={i}>
                  <span>{el[ this.label ]}</span>
                </li>,
            ) }
            </ul>
          );
        },
    
        props: {
    
          // use the generic type as prop type for 'options' array
          options: type( Array as () => T[] )
            .required,
    
          // use generic keyof T type for label
          label: type( String as () => string as () => keyof T )
            .required,
    
        },
    
      } );
    
    }
    

    Now my hope was that by calling the factory function with a specific type the prop types would assume this given type as well. Unfortunately this does not work:

    // Define type for factory function
    interface Option {
      readonly foo: string;
      readonly bar: number;
    }
    
    // call generic factory function and specify the type
    const MyComponent = myComponentFactory<Option>();
    
    component( {
    
      name: 'Container',
    
      render() {
        return (
          <MyComponent
            // 'options' now should be typed as Option[]
            // but it is still typed as T[]
            // TypeScript throws error because 'Option' is not assignable to 'T'
            options={this.myCompOptions}
    
            // 'label' should be typed foo | bar
            // but it is still typed as keyof T
            // again, Typescript error
            label={'foo'} />
        );
      },
    
      computed: {
    
        myCompOptions(): Option[] {
          return [
            {
              foo: 'baz1',
              bar: 1,
            },
            {
              foo: 'baz2',
              bar: 2,
            },
            {
              foo: 'baz3',
              bar: 3,
            },
          ];
        },
    
      },
    
    } );
    

    Are generic prop types even possible? Any idea how this could be handled?

    opened by thenickname 4
  • Converting a component with `convert` not returning a correct type

    Converting a component with `convert` not returning a correct type

    In 2.1.1, using the below code:

    export const VAvatar = ofType<Props, Events, ScopedSlots>().convert(
      VueAvatarOriginal,
    );
    

    the type of VAvatar is like the following:

    const VAvatar: VueConstructor<{
        _tsxattrs: TsxComponentAttrs<Props, Events, ScopedSlots>;
    } & Vue>
    

    but when I use with 2.2.0

    the type of VAvatar is like the following instead:

    const VAvatar: VueConstructor<any>
    
    opened by chanlito 4
  • Bump minimist from 1.2.5 to 1.2.8

    Bump minimist from 1.2.5 to 1.2.8

    Bumps minimist from 1.2.5 to 1.2.8.

    Changelog

    Sourced from minimist's changelog.

    v1.2.8 - 2023-02-09

    Merged

    Fixed

    Commits

    • Merge tag 'v0.2.3' a026794
    • [eslint] fix indentation and whitespace 5368ca4
    • [eslint] fix indentation and whitespace e5f5067
    • [eslint] more cleanup 62fde7d
    • [eslint] more cleanup 36ac5d0
    • [meta] add auto-changelog 73923d2
    • [actions] add reusable workflows d80727d
    • [eslint] add eslint; rules to enable later are warnings 48bc06a
    • [eslint] fix indentation 34b0f1c
    • [readme] rename and add badges 5df0fe4
    • [Dev Deps] switch from covert to nyc a48b128
    • [Dev Deps] update covert, tape; remove unnecessary tap f0fb958
    • [meta] create FUNDING.yml; add funding in package.json 3639e0c
    • [meta] use npmignore to autogenerate an npmignore file be2e038
    • Only apps should have lockfiles 282b570
    • isConstructorOrProto adapted from PR ef9153f
    • [Dev Deps] update @ljharb/eslint-config, aud 098873c
    • [Dev Deps] update @ljharb/eslint-config, aud 3124ed3
    • [meta] add safe-publish-latest 4b927de
    • [Tests] add aud in posttest b32d9bd
    • [meta] update repo URLs f9fdfc0
    • [actions] Avoid 0.6 tests due to build failures ba92fe6
    • [Dev Deps] update tape 950eaa7
    • [Dev Deps] add missing npmignore dev dep 3226afa
    • Merge tag 'v0.2.2' 980d7ac

    v1.2.7 - 2022-10-10

    Commits

    ... (truncated)

    Commits
    • 6901ee2 v1.2.8
    • a026794 Merge tag 'v0.2.3'
    • c0b2661 v0.2.3
    • 63b8fee [Fix] Fix long option followed by single dash (#17)
    • 72239e6 [Tests] Remove duplicate test (#12)
    • 34b0f1c [eslint] fix indentation
    • 3226afa [Dev Deps] add missing npmignore dev dep
    • 098873c [Dev Deps] update @ljharb/eslint-config, aud
    • 9ec4d27 [Fix] Fix long option followed by single dash
    • ba92fe6 [actions] Avoid 0.6 tests due to build failures
    • Additional commits viewable in compare view
    Maintainer changes

    This version was pushed to npm by ljharb, a new releaser for minimist since your current version.


    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump json5 from 2.1.3 to 2.2.3

    Bump json5 from 2.1.3 to 2.2.3

    Bumps json5 from 2.1.3 to 2.2.3.

    Release notes

    Sourced from json5's releases.

    v2.2.3

    v2.2.2

    • Fix: Properties with the name __proto__ are added to objects and arrays. (#199) This also fixes a prototype pollution vulnerability reported by Jonathan Gregson! (#295).

    v2.2.1

    • Fix: Removed dependence on minimist to patch CVE-2021-44906. (#266)

    v2.2.0

    • New: Accurate and documented TypeScript declarations are now included. There is no need to install @types/json5. (#236, #244)
    Changelog

    Sourced from json5's changelog.

    v2.2.3 [code, diff]

    v2.2.2 [code, diff]

    • Fix: Properties with the name __proto__ are added to objects and arrays. (#199) This also fixes a prototype pollution vulnerability reported by Jonathan Gregson! (#295).

    v2.2.1 [code, diff]

    • Fix: Removed dependence on minimist to patch CVE-2021-44906. (#266)

    v2.2.0 [code, diff]

    • New: Accurate and documented TypeScript declarations are now included. There is no need to install @types/json5. (#236, #244)
    Commits
    • c3a7524 2.2.3
    • 94fd06d docs: update CHANGELOG for v2.2.3
    • 3b8cebf docs(security): use GitHub security advisories
    • f0fd9e1 docs: publish a security policy
    • 6a91a05 docs(template): bug -> bug report
    • 14f8cb1 2.2.2
    • 10cc7ca docs: update CHANGELOG for v2.2.2
    • 7774c10 fix: add proto to objects and arrays
    • edde30a Readme: slight tweak to intro
    • 97286f8 Improve example in readme
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump qs from 6.5.2 to 6.5.3

    Bump qs from 6.5.2 to 6.5.3

    Bumps qs from 6.5.2 to 6.5.3.

    Changelog

    Sourced from qs's changelog.

    6.5.3

    • [Fix] parse: ignore __proto__ keys (#428)
    • [Fix] utils.merge: avoid a crash with a null target and a truthy non-array source
    • [Fix] correctly parse nested arrays
    • [Fix] stringify: fix a crash with strictNullHandling and a custom filter/serializeDate (#279)
    • [Fix] utils: merge: fix crash when source is a truthy primitive & no options are provided
    • [Fix] when parseArrays is false, properly handle keys ending in []
    • [Fix] fix for an impossible situation: when the formatter is called with a non-string value
    • [Fix] utils.merge: avoid a crash with a null target and an array source
    • [Refactor] utils: reduce observable [[Get]]s
    • [Refactor] use cached Array.isArray
    • [Refactor] stringify: Avoid arr = arr.concat(...), push to the existing instance (#269)
    • [Refactor] parse: only need to reassign the var once
    • [Robustness] stringify: avoid relying on a global undefined (#427)
    • [readme] remove travis badge; add github actions/codecov badges; update URLs
    • [Docs] Clean up license text so it’s properly detected as BSD-3-Clause
    • [Docs] Clarify the need for "arrayLimit" option
    • [meta] fix README.md (#399)
    • [meta] add FUNDING.yml
    • [actions] backport actions from main
    • [Tests] always use String(x) over x.toString()
    • [Tests] remove nonexistent tape option
    • [Dev Deps] backport from main
    Commits
    • 298bfa5 v6.5.3
    • ed0f5dc [Fix] parse: ignore __proto__ keys (#428)
    • 691e739 [Robustness] stringify: avoid relying on a global undefined (#427)
    • 1072d57 [readme] remove travis badge; add github actions/codecov badges; update URLs
    • 12ac1c4 [meta] fix README.md (#399)
    • 0338716 [actions] backport actions from main
    • 5639c20 Clean up license text so it’s properly detected as BSD-3-Clause
    • 51b8a0b add FUNDING.yml
    • 45f6759 [Fix] fix for an impossible situation: when the formatter is called with a no...
    • f814a7f [Dev Deps] backport from main
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump decode-uri-component from 0.2.0 to 0.2.2

    Bump decode-uri-component from 0.2.0 to 0.2.2

    Bumps decode-uri-component from 0.2.0 to 0.2.2.

    Release notes

    Sourced from decode-uri-component's releases.

    v0.2.2

    • Prevent overwriting previously decoded tokens 980e0bf

    https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.1...v0.2.2

    v0.2.1

    • Switch to GitHub workflows 76abc93
    • Fix issue where decode throws - fixes #6 746ca5d
    • Update license (#1) 486d7e2
    • Tidelift tasks a650457
    • Meta tweaks 66e1c28

    https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.1

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • IframeHTMLAttributes is missing properties

    IframeHTMLAttributes is missing properties

    Current IframeHTMLAttributes

    export interface IframeHTMLAttributes extends HTMLAttributes {
      allowfullscreen?: boolean;
      allowtransparency?: boolean;
      frameborder?: number | string;
      height?: number | string;
      marginheight?: number;
      marginwidth?: number;
      name?: string;
      sandbox?: string;
      scrolling?: string;
      seamless?: boolean;
      src?: string;
      srcdoc?: string;
      width?: number | string;
    }
    

    It's missing the following attributes:

    Just as a side-note, allowfullscreen is now a legacy attribute, allow="fullscreen" is preferred

    opened by moonquddus 0
Owner
null
Vue 3 jsx runtime support.

vue-jsx-runtime Vue 3 jsx runtime support. The background https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html . With new jsx ru

doly mood 10 Dec 2, 2022
Support template modifiers (.sync, .capture, etc) in JSX

babel-plugin-vue-jsx-modifier Support template modifiers (.sync, .capture, etc) in JSX Overview In Vue template, we can use some modifiers. See: .sync

null 5 Jan 28, 2023
A Laravel Mix extension for Vue 3, Typescript and JSX.

Laravel Mix v5 - Vue 3 A Laravel Mix extension for Vue 3, Typescript and JSX. Deprecated use Laravel Mix v6 Usage First, install the extension. npm in

Georges KABBOUCHI 23 Nov 15, 2022
JSX Syntactic Sugar Plugin for Vue Functional Components

DEPRECATED: Check https://github.com/vuejs/jsx instead JSX Functional Components for Vue JSX This babel plugin adds some syntactic sugar to JSX. Usage

Nick Messing 66 May 26, 2022
Jsx-runtime for vue 3

vue-jsx-runtime-examples vue-jsx-runtime examples

doly mood 1 Apr 8, 2022
CSS encapsulation solution for Vue JSX

babel-plugin-vue-jsx-scoped-css ?? CSS encapsulation solution for Vue JSX About This plugin is used to implement the css scoped effect of template in

minfive 2 Mar 20, 2021
JSX for Vue 3

Babel Plugin JSX for Vue 3.0 To add Vue JSX support. English | 简体中文 Installation Install the plugin with: npm install @vue/babel-plugin-jsx -D Then ad

vuejs 1.5k Jan 3, 2023
Babel preset for transforming Vue JSX.

babel-preset-vue Babel preset for all Vue plugins. Install npm install -D babel-preset-vue CDN: UNPKG Usage In your .babelrc: { "presets": ["vue"] }

vuejs 85 Dec 19, 2022
babel plugin for vue 2.0 jsx

babel-plugin-transform-vue-jsx Babel plugin for Vue 2.0 JSX Babel Compatibility Notes If using Babel 7, use 4.x If using Babel 6, use 3.x Requirements

vuejs 1.8k Dec 3, 2022
Shrimpit 🍤 is a small CLI analysis tool for checking unused JavaScript, JSX & Vue templates ES6 exports in your project.

Shrimpit ?? Shrimpit is a small CLI analysis tool for checking unused JavaScript, JSX & Vue templates ES6 exports in your project. Install npm npm i -

Davy Duperron 260 Nov 29, 2022
Event modifiers syntactic sugar for JSX

Event Modifiers for JSX DEPRECATED: Check https://github.com/vuejs/jsx instead This babel plugin adds some syntactic sugar to JSX. Usage: npm i babel-

Nick Messing 45 Aug 31, 2021
JSX Syntactic Sugar Plugin for v-model

DEPRECATED: Check https://github.com/vuejs/jsx instead JSX v-model for Vue JSX This babel plugin adds some syntactic sugar to JSX. Usage: npm i babel-

Nick Messing 154 Feb 28, 2022
Automatically imports createElement as h when writing JSX and functional syntax that supports only setup() and template refs that supports setup()

babel-preset-vca-jsx Support for automatic import of createElement as h and setup functional component syntax and setup template refs Feature Automati

lululuffy 73 Aug 24, 2022
A babel plugin that provides jsx syntax for vue3

vue-next-jsx This project has been archived because Vue will have an official version. Vue Next JSX Explorer A babel plugin that provides jsx syntax f

Chunyang Huo 89 Aug 11, 2022
A simple Vue 3 plugin for handling browser cookies with typescript support

A vue 3 plugin for handling browser cookies with typescript support. Load and save cookies within your Vue 3 application

Anish George 44 Nov 23, 2022
Support for TypeScript's path mapping in Vite

vite-tsconfig-paths Give vite the ability to resolve imports using TypeScript's path mapping. Usage Install as dev dependency Inject vite-tsconfig-pat

Alec Larson 663 Jan 7, 2023
🍍Automatically Typed, Modular and lightweight Store for Vue using the composition api with DevTools support

??Automatically Typed, Modular and lightweight Store for Vue using the composition api with DevTools support

Eduardo San Martin Morote 9.5k Dec 30, 2022
A vue code diff display plugin, support Vue2 / Vue3

A code diff display plugin, available for Vue2 / Vue3. It is the vue3 version of vue-code-diff, refer to a lot of code, thanks here.

Shimada666 136 Jan 5, 2023
vue prop typescript

Prop type definition of Vue3. only recommended for typescript.

LvXiaoBu 4 Jul 27, 2022