I'm trying to get web workers playing nice with Typescript and Webpack's worker-loader. There's an example in their documentation of achieving this through a custom module declaration, however this relies on using the webpack worker-loader!./myWorker
syntax.
I want to be able to load workers through a custom *.worker.js
webpack use
rule rather than explicitly listing the loader in the import string. Something about typescript doesn't seem to like defining or modifying a modules declaration if it's a plain relative import, and gets stuck on the fact that the worker file is not a module, even with a module declaration for it.
I have a worker that looks like
// test.worker.ts
/// <reference lib="webworker" />
const worker: DedicatedWorkerGlobalScope = self as any;
worker.onmessage = ({ data }) => {
if (data instanceof Array) {
worker.postMessage(data.join(' ') + '!');
}
};
A declaration that looks like
// custom.d.ts
declare module '*.worker' {
class TestWorker extends Worker {
constructor();
}
export default TestWorker
}
And is used in my main app as
import TestWorker from './test.worker';
const testWorker = new TestWorker();
testWorker.onmessage = ({ data }: { data: string }) => {
console.log(data);
};
testWorker.postMessage([
'hello',
'I',
'am',
'a',
'web',
'worker',
]);
The error output is
TypeScript error in /worker-test/src/index.tsx(9,24):File '/worker-test/src/test.worker.ts' is not a module. TS2306
Changing the import to worker-loader!./test.worker
seems to work and gets typescript to understand the custom declaration, however I'm really trying to avoid using custom loader strings as the intention is to integrate this into create-react-app which doesn't allow these.
Is there a way to get regular relative imports to recognise a custom module declaration?
You were almost there!
Change the module declaration to include the file extension:
// custom.d.ts
declare module '*.worker.ts' {
class TestWorker extends Worker {
constructor();
}
export default TestWorker
}
And your import to also include the file extension:
import TestWorker from './test.worker.ts';
This did it for me - specifying the extension in the import stops TS from importing it as a module, and specifying the extension in the declaration stops TS from complaining since you're importing a .ts
file by also specifying the extension.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With