Hi! First of all, thanks for the project.
I'm trying to use vue-jsx-vapor in a regular Vue + Vite application that contains mostly .vue SFCs and a few .tsx components using vue-jsx-vapor macros.
Vite is configured as:
import vue from '@vitejs/plugin-vue'
import vueJsxVapor from 'vue-jsx-vapor/vite'
export default defineConfig({
plugins: [
vueJsxVapor({
interop: true,
macros: true,
}),
vue(),
],
})
The build works as expected, but I'm a bit unsure about the recommended type-checking workflow.
From my understanding:
vue-tsc understands .vue files, but doesn't apply TS Macro transforms to standalone .tsx files.
tsmc applies the macro transforms, but doesn't understand .vue SFCs.
This becomes tricky when .vue and .tsx files import each other, since TypeScript follows imports across the boundary.
As an experiment, I wrote a custom checker that uses @volar/typescript's runTsc() and registers both the Vue language plugin and the TS Macro language plugins in the same TypeScript run. That seems to work well for mixed .vue + .tsx projects.
vue-ts-macro-tsc
#!/usr/bin/env node
const { runTsc } = require('@volar/typescript/lib/quickstart/runTsc');
const vueCore = require('@vue/language-core');
const tsMacro = require('@ts-macro/language-plugin');
const tsMacroOptions = require('@ts-macro/language-plugin/options');
const windowsPathReg = /\\/g;
let runExtensions = ['.vue', '.ts', '.tsx'];
let extensionsChangedException;
function unique(items) {
return [...new Set(items)];
}
function getVueOptions(ts, options) {
const { configFilePath } = options.options;
if (typeof configFilePath === 'string') {
return vueCore.createParsedCommandLine(
ts,
ts.sys,
configFilePath.replace(windowsPathReg, '/'),
).vueOptions;
}
return vueCore.createParsedCommandLineByJson(
ts,
ts.sys,
(options.host ?? ts.sys).getCurrentDirectory(),
{},
).vueOptions;
}
function run() {
return runTsc(
require.resolve('typescript/lib/tsc'),
{
extraSupportedExtensions: runExtensions,
extraExtensionsToRemove: [],
},
(ts, options) => {
const vueOptions = getVueOptions(ts, options);
const allExtensions = unique([
...vueCore.getAllExtensions(vueOptions),
'.ts',
'.tsx',
]);
if (
runExtensions.length !== allExtensions.length ||
!runExtensions.every((ext) => allExtensions.includes(ext))
) {
runExtensions = allExtensions;
throw (extensionsChangedException = new Error('extensions changed'));
}
const vueLanguagePlugin = vueCore.createVueLanguagePlugin(
ts,
options.options,
vueOptions,
(id) => id,
);
const macroLanguagePlugins = tsMacro.getLanguagePlugins(
ts,
options.options,
tsMacroOptions.getOptions(ts),
);
return {
languagePlugins: [...macroLanguagePlugins, vueLanguagePlugin],
};
},
"require('typescript')",
);
}
try {
run();
} catch (error) {
if (error === extensionsChangedException) {
run();
} else {
throw error;
}
}
So I was wondering:
- Is this kind of combined checker the intended approach?
- Or is there another recommended workflow for projects that mix Vue SFCs and
vue-jsx-vapor TSX files?
From the perspective of someone starting from the standard Vue + Vite template, I expected the setup to be roughly:
npm install vue-jsx-vapor
Configure the Vite plugin, and have both vite build and npm run type-check continue to work.
If I'm overlooking the intended setup, I'd really appreciate any guidance.
Thanks!
Hi! First of all, thanks for the project.
I'm trying to use
vue-jsx-vaporin a regular Vue + Vite application that contains mostly.vueSFCs and a few.tsxcomponents usingvue-jsx-vapormacros.Vite is configured as:
The build works as expected, but I'm a bit unsure about the recommended type-checking workflow.
From my understanding:
vue-tscunderstands.vuefiles, but doesn't apply TS Macro transforms to standalone.tsxfiles.tsmcapplies the macro transforms, but doesn't understand.vueSFCs.This becomes tricky when
.vueand.tsxfiles import each other, since TypeScript follows imports across the boundary.As an experiment, I wrote a custom checker that uses
@volar/typescript'srunTsc()and registers both the Vue language plugin and the TS Macro language plugins in the same TypeScript run. That seems to work well for mixed.vue+.tsxprojects.vue-ts-macro-tsc
So I was wondering:
vue-jsx-vaporTSX files?From the perspective of someone starting from the standard Vue + Vite template, I expected the setup to be roughly:
Configure the Vite plugin, and have both
vite buildandnpm run type-checkcontinue to work.If I'm overlooking the intended setup, I'd really appreciate any guidance.
Thanks!