Vue TSX Type Support

3.2.0 · maintenance · verified Sun Apr 19

vue-tsx-support is a TypeScript support library designed to enable and enhance the use of TSX (JSX for TypeScript) within Vue 2 applications. Currently at version 3.2.0, this package primarily functions as a type checker, providing robust type safety for JSX syntax used in Vue 2 components. It is crucial to note that vue-tsx-support does not handle JSX transpilation; users must integrate a separate Babel preset (such as `@vue/babel-preset-jsx`) for this purpose. A key differentiator is its explicit focus on the Vue 2 ecosystem; it does not support Vue 3, which incorporates its own JSX type checking mechanisms that are incompatible. The library supports various component styles, including object-style, class-style (with `vue-class-component`), and `@vue/composition-api`, with specific instructions for each. The project is largely in a maintenance phase, as its core functionality is tied to the now older Vue 2 major version.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to define a type-safe TSX component with props and emitted events using `createTsxComponent` and how to consume it in a parent component, including the necessary global type import.

// tsconfig.json excerpt
// {
//   "compilerOptions": {
//     "jsx": "preserve",
//     "jsxFactory": "VueTsxSupport",
//     "target": "esnext",
//     "module": "esnext",
//     "strict": true
//   },
//   "include": [
//     "src/**/*.ts",
//     "src/**/*.tsx",
//     "src/**/*.vue",
//     "node_modules/vue-tsx-support/enable-check.d.ts" // Alternative to explicit import
//   ]
// }

// src/components/MyCounter.tsx
import Vue from 'vue';
import { createTsxComponent } from 'vue-tsx-support';

interface MyCounterProps {
  initialValue?: number;
  label: string;
}

interface MyCounterEvents {
  onChange: (newValue: number) => void;
}

const MyCounter = createTsxComponent<MyCounterProps, MyCounterEvents>({
  name: 'MyCounter',
  props: {
    initialValue: { type: Number, default: 0 },
    label: { type: String, required: true },
  },
  data() {
    return { count: this.initialValue };
  },
  methods: {
    increment() {
      this.count++;
      this.$emit('change', this.count);
    },
    decrement() {
      this.count--;
      this.$emit('change', this.count);
    },
  },
  render() {
    return (
      <div>
        <span>{this.label}: {this.count}</span>
        <button onClick={this.increment}>+</button>
        <button onClick={this.decrement}>-</button>
      </div>
    );
  },
});

export default MyCounter;

// src/App.tsx (Example usage in a parent component)
import Vue from 'vue';
import MyCounter from './components/MyCounter';

// Crucial for global type checking of JSX intrinsic elements like 'div', 'span'
import 'vue-tsx-support/enable-check';

export default Vue.extend({
  name: 'App',
  data() {
    return { totalCount: 0 };
  },
  methods: {
    handleCounterChange(newValue: number) {
      this.totalCount = newValue; // In a real app, this might accumulate counts
      console.log(`Counter changed to: ${newValue}`);
    },
  },
  render() {
    return (
      <div>
        <h1>Vue TSX Application</h1>
        <p>Current Total: {this.totalCount}</p>
        <MyCounter label="Counter 1" initialValue={5} onChange={this.handleCounterChange} />
        <MyCounter label="Counter 2" onChange={this.handleCounterChange} />
      </div>
    );
  },
});

view raw JSON →