You can use TypeScript in a preload file (or any file). Just import the ts-node package and configure it before you import any of your TypeScript code.
F.e., make an index.js file containing:
require('./require-hooks')
module.exports = require('./entry') // this is your TypeScript entry point.
then in your require-hooks.js file configure ts-node (ts-node is a require hook that compiles TypeScript on the fly, with caching for subsequent runs):
// ability to require/import TypeScript files
require('ts-node').register({
typeCheck: false, // faster, no type checking when require'ing files. Use another process to do actual type checking.
transpileOnly: true, // no type checking, just strip types and output JS.
files: true,
// manually supply our own compilerOptions, otherwise if we run this file
// from another project's location then ts-node will use
// the compilerOptions from that other location, which may not work.
compilerOptions: require('./tsconfig.json').compilerOptions,
})
Note, you can put all sorts of require hooks in there, for example so you can do things like require('path/to/file.ts'), require('path/to/file.tsx'), require('path/to/file.jsx'), require('path/to/file.png'), require('path/to/file.mp3'), etc, where you can define hooks for handling certain types of files (similar to Webpack in some way, but hooking into Node's builtin require function). For example, @babel/register is a hook for running JS files through Babel, asset-require-hook is a require hook that allows you to import assets like JPG files, yaml-hook allows you to require .yaml files. EDIT: Even more: css-modules-require-hook for importing CSS modules, and module-alias for creating aliases like with WebPack.
The pirates lib is a popular tool for making your own require hooks, though I also find it easy to make hooks manually without a library. You can, for example, override Module.prototype.require to implement some simple hooks:
const path = require('path')
const url = require('url')
const Module = require('module')
const oldRequire = Module.prototype.require
function toFileURL(filePath) {
return url.format({
pathname: filePath,
protocol: 'file:',
slashes: true,
})
}
Module.prototype.require = function(moduleIdentifier) {
// this simple hook returns a `file://...` URL when you try to `require()`
// a file with extension obj, svg, png, or jpg.
if (['.obj', '.png', '.svg', '.jpg'].some(ext => moduleIdentifier.endsWith(ext))) {
const result = String(toFileURL(path.resolve(path.dirname(this.filename), moduleIdentifier)))
result.default = result
return result
} else {
return oldRequire.call(this, moduleIdentifier)
}
}
then in some other file,
const fs = require('fs')
const img = require('path/to/foo.jpg')
console.log(img) // file:///absolute/path/to/foo.jpg
document.createElement('img').src = img
You could even move the call to document.createElement('img').src = img into your overridden require method to do it automatically and return the img element instead of returning a file:// URL. :)
Finally, in your ./entry.ts file that the above index.js file imports, you can have any TypeScript in there.