note:
After spending countless hours on this, I finally had a breakthrough today. It turns out that changing transpileOnly to false made all the difference:
chainWebpack: config => {
const getCustomTransformers = program => ({
before: [keysTransformer(program)]
});
const transpileOnly = false;
["ts", "tsx"].forEach(rule => {
config.module
.rule(rule)
.use("ts-loader")
.loader("ts-loader")
.tap(options => Object.assign(options, { getCustomTransformers, transpileOnly }));
});
},
This actually worked! I can now see my interface's keys in the console. The only thing bothering me now is whether I'm breaking something by making this change. Is there a better or safer way to achieve the same result?
original post:
I have a hunch that ts-loader's transpileOnly: true,
setting may not play nice with transformers. If that's the case, what are my options? Any insights would be greatly appreciated. The transformer causing the issue is Kenji Imamula's ts-transformer-keys
You probably need a good understanding of both webpack and typescript to tackle this problem. If you're like me - working with it but not deep into the core functionality - you might benefit from learning about transformers through this helpful guide: how to write a TypeScript transform plugin
Although I am familiar with webpack, working with Vue 3 for the first time introduced some challenges due to its different configuration setup. To modify the webpack config, you use vue.config.js file along with webpack-merge or webpack-chain. As I needed to tweak the ts loaders, I used chain... alongside a few other configurations. Here's how my vue.config.ts looks like:
const PackageVars = require('./package-vars.webpack-plugin.js')
const keysTransformer = require('ts-transformer-keys/transformer').default
module.exports = {
configureWebpack: {
plugins: [PackageVars]
},
chainWebpack: config => {
const getCustomTransformers = program => ({
before: [keysTransformer(program)]
})
;['ts', 'tsx'].forEach(rule => {
config.module
.rule(rule)
.use('ts-loader')
.loader('ts-loader')
.tap(options => Object.assign(options, { getCustomTransformers }))
})
},
pluginOptions: {
i18n: {
locale: 'en',
fallbackLocale: 'en',
localeDir: 'locales',
enableInSFC: true
}
},
// additional css configuration goes here
}
Running this generates a webpack.config.js (truncated for brevity) as shown when using vue inspect command:
{
...
}
// more webpack configuration follows...
In my code implementation, after appending the demo from the readme to an interface in a .ts file, I expected it to work seamlessly:
import { keys } from "ts-transformer-keys";
export interface FirebaseUser {
uid: string;
displayName?: string;
email?: string;
phoneNumber?: string;
emailVerified: boolean;
isAnonymous?: boolean;
}
const keysOfProps = keys<FirebaseUser>();
console.log({ keysOfProps });
This was supposed to simplify complex factory methods significantly:
export function factoryFirebaseUser(
data = <Partial<FirebaseUser>>{}
): FirebaseUser {
if (!data.hasOwnProperty("uid")) {
data.uid = undefined;
}
//...
return data as FirebaseUser;
}
However, upon running npm run serve, I encountered an error:
Uncaught ReferenceError: keys is not defined
. Can anyone help me identify where else I need to include it?
I suspect that the transpileOnly: true,
setting in the loader config could be causing this issue. My understanding is that this setting allows separate babel configurations.