Closed d2s closed 5 years ago
Have you tried it yourself, yet? If so, where did you get stuck? (I'm not a fan of TypeScript, personally).
As far as I understand, the only current way to do so is through using the --watch
flag that will transpile the code whenever there's a change; eleventy then picks up on these changes through its own --watch
and rebuilds corresponding part of the website.
In theory, this works fine, but it presents a huge burden on our workload, as you now have to wait for 2 processes to happen in sequence before you can see any change propagate. I've recently gotten into the same situation when trying to use Svelte as a template engine for specific parts of my site, and would love to know if there's any specific implementation that mitigates this problem.
My current implementation is as follow:
.11ty.js
template I import the Server.js
bundle, run the SvelteApp.render()
method that return an html
string, which I then return in the Eleventy layout;<script src="svelteApp.js" defer>
that refers to the client bundle generated by Rollup;dist
folder that Eleventy then picks up through addPassthroughCopy
;eleventy --serve
and hope for the best.Problems:
.11ty.js
templates don't update until I run eleventy --serve
again, even though Eleventy does notice a change and rebuilds the website, very odd behavior. This makes testing the SSR impossible while developing, as changes to the Server.js
don't get reflected in the browser;.11ty.ts
templates, as they simply wouldn't change. Worth the shot, though!NOTE: I know this is not related directly to Typescript, but as I'm dealing with transpilation much like you'd with TS, this might be of help. If needed, I can transfer the svelte discussion somewhere else đ€
Hmm, stabbing in the dark here, but a few things that might stoke the fire:
eleventy --watch
: bring your own dev server and Eleventy will rebuild to eleventyConfig.dir.output
Another thing to consider: put all your .ts
files into _includes
; Eleventy will automatically watch all files in _includes
and rebuild. Not ideal. (I end up sometimes putting static files into _includes
just for the sake of triggering a rebuild when running eleventy --serve|watch
)
Maybe take advantage of the new(ish) JS dependencies watch config flag. Maybe there's a way you could generate a file that require()
s your typescript files somehow, which could instruct Eleventy to spider into your .ts
files, thereby buying you free watch
ing.
Or you could even require them from .eleventy.js
and not even consume them, again simply to trigger rebuilds and free watch
.
Even more food for thought: Eleventy can write template files into _includes
and avoid writing them to eleventyConfig.dir.output
, which has its (albeit sparse) uses.
For some strange reason, .11ty.js templates don't update until I run eleventy --serve again...
That's odd, I haven't noticed this. Maybe I experience the same and simply haven't noticed, or maybe there's something else going on.
I end up sometimes putting static files into
_includes
I symlinked some :-)
@Ryuno-Ki good call!
Ultimately, it'll be much easier handling .ts
when #117 comes up
Wow #117 has 53 upvotes!
I would definitely say this is dependent on #117 but Iâll go ahead and put this into the enhancement queue since itâs kind of a standalone thing.
This repository is now using lodash style issue management for enhancements. This means enhancement issues will now be closed instead of leaving them open.
View the enhancement backlog here. Donât forget to upvote the top comment with đ!
@jevets Thanks for the thought process, I ended up settling for parallel Rollup and PostCSS processes that paste files in a folder that Eleventy picks up with pass-through copy. It's working nicely, but the 11ty.js
updating problem is still a reality, I even filed an issue on this #596 đ
Would be amazing if you could try reproducing it o/
In addition to the other tweaks with --watch
suggested above, I found that using ts-node
and just registering it at the top of the .eleventy.js
file works quite nicely.
Alas, it does not trigger rebuilds for changes to the config (I think that's expected?), but it does build everything correctly⊠and you can use one small hack to be able to watch for changes to .ts
files in the main app area without needing to drive it through a separate watcher. Instead of making a .11ty.js
file which has all the implementation, have a .11ty.ts
file which the .11ty.js
file imports and then simply re-exports.
(That blog post will probably be late this week or sometime next week; feel free to just poke at the source in the meantime. It includes type defs for most of the API surface of Eleventy! I plan to get those on DefinitelyTyped by the end of the year.)
I plan to get those on DefinitelyTyped by the end of the year.
That would be much much appreciated, @chriskrycho !
Iâll see if I can get them up. Just as Iâm moving off of 11ty to my own thing! (Not 11tyâs fault. Just finally getting a handle on doing exactly what Iâve wanted to for half a decade!)
As I get more experience with using JSDoc annotations for typechecking using tsc
, I can use TypeScript for serving some type annotations.
That could lead to a .d.ts
file for type checks (and the rest of the code base in .js).
Would that be something worthwhile for everyone?
Hey @Ryuno-Ki is there any update on including a type declaration file, so TypeScript users can import Eleventy from @11ty/eleventy
without getting error TS7016: Could not find a declaration file for module '@11ty/eleventy'.
?
Do feel free to steal from mine, which are still mostly accurate but now a bit out of date. (I havenât switched off of 11ty, but I also havenât had time to publish those in any way, and likely wonâtâjust not at or anywhere near the top of my priority list).
(I'm unsubscribing from this, so won't see further conversation in general.)
Hmm, I tried saving that file as types/eleventy.d.ts
in my project, but it didn't work. I've tried 100 different TypeScript configuration settings, still doesn't work. đ€· I ended up replacing that with declare module '@11ty/eleventy'
, which should work like a sledgehammer, but still doesn't.
Not that I expect anyone to look at my code, but here's my current setup, if anyone has 2 minutes to look it over for something I might be missing. My Eleventy build code is in /bin/build.ts
. Runs on npm start
; requires Node 17.
@paulshryock without looking at your project, take a look at the tsconfig.json
and my .eleventy.js
files in my project as well. The former will make types resolve correctly; the latter just imports a bunch of TS files to author in (specifically one major file for the actual config) and runs them using ts-node
. The root file itself wasnât able to be authored in TS when I built that type definition, so I had the .eleventy.js
just use the TS files.
Yeah I checked out those files. I'm already using ts-node
in my CLI build script like node --es-module-specifier-resolution=node --loader ts-node/esm bin/build.ts
, but I'll play around with it some more. I might end up just using Eleventy via CLI--not the end of the world, but was hoping to use the new Programmatic API from v1.0.0. Thanks!
I was in need of this very setup, after some trial and error I got it all working pretty nicely. TypeScript doesn't necessarily have to be supported by 11ty for people to make use of it.
I wrote a very short article on how I went about it below: https://www.jameshill.dev/articles/typescript-and-11ty/
There's also a fully kitted out starter that I mention in the article: https://github.com/jahilldev/11tyby
Nice writeup @jhukdev!
For my use case I'm importing 11ty programmatically, and that's where the missing type information becomes a problem.
import Eleventy from '@11ty/eleventy'
(async function() {
const elev = new Eleventy()
await elev.write()
})()
fwiw I've had success using esbuild-runner to run the project (mostly) out of the box. You'll probably need to use the --cache
argument to get parsing working properly in templates.
I use this patch-package
with this patch to add TypeScript file extension awareness to 11ty (and force some cache invalidation, so esbuild-runner can play nicely.)
Then you can invoke 11ty with: yarn esr --cache ./node_modules/.bin/eleventy --config ./.eleventy.ts [command...]
(I wrapped it in an alias, so it's transparent for me).
Here is an 11ty template in typescript in case anyone needs it (I didn't see it in any of the links in this thread -- though I might have missed it):
I did want to reference this one too using the new addExtension API
@zachleat Ahh this is an interesting solution! I hadn't considered this approach, thanks! đ
You all may be interested in #2279 which was the smallest patch that was able to get @notjosh's solution to work. It does require running Eleventy with a transpiler like esbuild-runner, esbuild-register, or ts-node but it just works from there.
This was bugging me so I shipped a drop-in solution. I was able to get a fair bit covered. Methods are JSDoc annotated with relative links to online documentation on the 11ty website. There is no support for plugin types, ie: eleventyConfig.addPlugin(somePlugin, {})
will not give you anything. There is not much that can really be done about that without manually typing them and relying on something like typeof
for comparison. This due to the way plugins are consumed by Eleventy.
In any sense, these configuration supported typings should help in productivity.
Surprisingly 11ty
was not taken on the registry. Given this solution is geared towards the project as a whole, it can be consumed as such. Keep in mind the @11ty/eleventy
is a peer and you need to install it too.
As per https://github.com/11ty/eleventy/issues/577#issuecomment-1127734319 the module can be consumed using @panoply/11ty
pnpm add @panoply/11ty
https://github.com/panoply/11ty
https://user-images.githubusercontent.com/7041324/168457886-4f21a4a1-4316-45fd-ba51-2c0092517113.mov
This was bugging me so I shipped a drop-in solution. I was able to get a fair bit covered. Methods are JSDoc annotated with relative links to online documentation on the 11ty website... these configuration supported typings should help in productivity.
Thanks @panoply! Any work towards getting types for Eleventy is much appreciated, and I'm sure many people will find this useful.
Surprisingly
11ty
was not taken on the registry. Given this solution is geared towards the project as a whole, it can be consumed as such. Keep in mind the@11ty/eleventy
is a peer and you need to install it too.
Why wouldn't typings just be included in Eleventy core via a pull request, or added to a potential @types/11ty
package via https://github.com/DefinitelyTyped/DefinitelyTyped?
Having some types for just the eleventy config object in a 3rd-party repo maintained by 1 person, using the global package name 11ty
seems like not the right way to go. And is potentially typo-squatting. Many people will npm install 11ty
without realizing that they're not installing Eleventy core directly. This seems like a potential security vulnerability down the road. cc: @zachleat
@panoply I'm not against having your own personal wrapper for any project, but couldn't it be namespaced like @panoply/11ty
?
Edit: Instead of "And is potentially typo-squatting", I should have said something like "And could have the unintended result of becoming a typo-squatting vulnerability". I didn't mean to directly or indirectly imply any malicious activity from @panopoly. Forgive me for coming off a little too harsh in my above comment.
Why wouldn't typings just be included in Eleventy core via a pull request, or added to a potential @types/11ty package via https://github.com/DefinitelyTyped/DefinitelyTyped?
When leveraging an .eleventy.js
file the export expects a function, eg: module.exports = function(eleventyConfig) {}
. Making a PR on DefinitelyTyped (though I'd be happy to PR there) it would not solve this issue in an elegant manner as the user would still need to annotate with JSDocs, eg: @type {import('..')}
and as such, the issue at hand persists. The wrapper eliminates that extra step and having scoured the issues it seems folks have had trouble understanding how JS Doc annotated types. There is also the aspect of editors, as JSDocs annotated types are a feature of the TypeScript LS. Some editors (AFAIK) do not employ the TS language server and handle such logic differently.
Types are assumed and should not require JSDoc comment annotations, hence the wrapper. The same logic is employed with other projects, for example in Rollup you can import defineConfig
to pull in type completions within the rollup.config.js
file. It is probably important to note that some consideration was taken here and it goes beyond configuration types, but also my hopes is that an approach can be establish for type completion in 11ty plugins. As it stands, Eleventy digests plugins from the method addPlugin(plugin, opts)
and as such this makes it a little difficult to pass completions.
Having some types for just the eleventy config object in a 3rd-party repo maintained by 1 person, using the global package name 11ty seems like not the right way to go.
Agreed. It is important to note that given the module is directly focused for 11ty the thought process is completely targeted towards the project users. In addition, the module has a peer on (@11ty/eleventy
) but in saying that, I'd be more than happy to relinquish ownership of the registry name and pass it to 11ty and your core team. I don't want to rustle any feathers here and it seems I am doing just that.
I'm not against having your own personal wrapper for any project, but couldn't it be namespaced like @panoply/11ty?
Again, I'd be happy to pass it over. My intentions are anything but "typo-squatting" and far more focused on actionable steps to bring type support into Eleventy. This issue per-say has seen no traction and it is rather difficult to get PR's merged or considered.
Registry name 11ty
was removed as per https://github.com/11ty/eleventy/issues/577#issuecomment-1127734319 and instead can be consumed via @panoply/11ty
- Might be worth getting it under the org sooner rather than later @paulshryock
@panoply, I apologize if it seemed like my feathers were rustled or if I was telling you what to do. I have no affiliation with Eleventy (I'm just a user), and was just trying to voice concerns for further discussion. I hear what you're saying about the technical implementation--how your approach as-is seems to work better for now as a module wrapper. Your explanation was helpful.
My intentions are ... focused on actionable steps to bring type support into Eleventy.
I think anything that brings us closer to TypeScript support is a good thing, so I just want to reiterate my thanks for your hard work on this--and hopefully assure you that I wasn't trying to call you out or accuse you of doing anything wrong. (Reading back over my initial comment; it may have sounded harsher than I meant--sorry!)
This issue per-say has seen no traction and it is rather difficult to get PR's merged or considered.
I wasn't aware of this--did you try opening a PR to add the relevant type declarations in this repo?
@paulshryock No apologies needed, I didn't think you were calling me out, but hearing how you voiced your concerns, I didn't want folks to think I had malicious intent or anything like this.
My thoughts in using the 11ty
name were because the module is literally a single line of code, eg: module.exports = cb => cb
and it requires eleventy's core as a peer. I could of gone as far as printing a disclaimer on postinstall
- it felt fitting (to me) that is just me. Either way, I removed the registry name and instead did as you recommended.
I wasn't aware of this--did you try opening a PR to add the relevant type declarations in this repo?
So 11ty is somewhat known for this and personally, I do not consider it a bad thing, I mean the less contributions sometimes the better the code. Look at the success of esbuild and how Evan approaches his project, so I wouldn't want to bother core maintainers with something a frivolous as this. Previous discussions and issues relating to this have pretty much died out or gone stale.
Though I could PR it wouldn't be fast tracked and folks in the past have made somewhat similar PR's or opened dialogue but nothing has come fruition.
Shipping this as wrapper module allows users to simply pnpm add 11ty
pnpm add @panoply/11ty
, pass it to module.exports
and Eleventys types will be at their fingertips. Because the module is mostly a declaration, PRs would be fast and much easier to wrangle because its a tiny 3rd-party repo maintained by 1 person.
Eventually it would be a good thing to have either TypeScript types and improved JSDoc annotations as part of Eleventy itself. Understandably popularity of Eleventy has grown a lot over the years, as the project slowly changed from a personal project of Zack to something more. Still, almost all of the code changes are made by him, so any major changes would need agreement from Zack.
Problem with 3rd party types is that those often get outdated quite fast, even for projects with a reasonably low amount of changes. Question is also about who is the target audience.
Even while the weekly downloads of @11ty/eleventy
https://www.npmjs.com/package/@11ty/eleventy package are around ~37-43K downloads, it is still a limited how many of those users are making more advanced customizations of Eleventy itself. Having better types would improve developer experience for part of people, but would require reasonable amount of effort to keep updated.
When looking at https://github.com/11ty/eleventy/graphs/contributors statistics, it shows that there are ~70 contributors in total, and most of those are with ~1-4 commits in total (per person). Situation would be a bit different if there would be multiple active contributors to the main Eleventy codebase. Extensions have variety of contributors, but what matters here most is how main codebase is developed. We can't make any decisions on behalf of Zach. But we can ask for his opinions about the future directions of Eleventy. Understandably he has a bit more time & focus for the overall project at the moment, so it would be interesting to see where this goes in the future.
@d2s Given the current architecture shipping types without needing to reach for JSDocs annotations can only be realistically achieved by passing module.exports
a function. There is no way of achieving this without a wrapper because the default export is a class:
const Eleventy = require("@11ty/eleventy");
// Create an instance
const eleventy = new Eleventy()
Those developers using the default class export (ie: programmatic control) can indeed benefit from DefinitelyTyped but it will not solve the issue for developers using the .eleventy.js
configuration file and I'm going to assume the majority are using the latter based on the plugin ecosystem and the streamlined control for generated site customizations. Given the .eleventy.js
configuration file expects a function there is no way types can be asserted without comment annotation:
module.exports = function(eleventyConfig) {}
Currently, folks who are leveraging comment JSDoc annotations need to do this:
/**
* @type {import('@11ty/eleventy')}
*/
module.exports = function(eleventyConfig) {}
Such an approach is extraneous and not necessarily fluent for a couple of reasons.
The simplest way to negate JSDoc annotation and also feed Type support is passing a function callback. This is a common practice across multiple projects, it also separates logic and keeps things clean, upkeep is easy and logic is kept separated from the core.
This is to some degree why I went the 11ty
registry name. It holds some degree of virtue and would exist as an opt-in that infers relation to the core project. If users want Typings, they can simply install it, pass module.exports
the function callback. No need for comment annotations or relying on the TS LS/compiler to generate them from the source. The approach allows the default class export to persist and it does not introduce any breaking changes.
Problem with 3rd party types is that those often get outdated quite fast, even for projects with a reasonably low amount of changes. Question is also about who is the target audience.
I don't necessarily agree here (well to an extent). The methods eleventyConfig
exposes is not going to drastically change to a point where third party types would become so outdated that they could not be leveraged. In any sense the TS nexus is vigorously maintained by folks because a lot of developers rely on IntelliSense capabilities. The same argument could be made for DefinitelyTyped typings as a third-party.
I'd argue a third party plugin to be less intimidating for folks to submit a PR opposed to DT. The simple approach here (IMO) is to keep this an opt-in, ship it under the @11ty org and allow the community or core maintainers to monitor its health. This way, the core codebase can exist and no breaking changes are imposed.
Doing this:
const eleventy = require('@panoply/11ty')
module.exports = eleventy(function(eleventyConfig) {
// etc etc
return {}
})
Lifts the burden from the Eleventy maintainers, they can focus on the JS purity of the project and need not bother about merging or reviewing PR's on core code which are pertaining to types. Anyway, that is just my two cents and if the core team and @zachleat want I'd be happy to assist in maintaining such a module under the org.
Hey @Ryuno-Ki is there any update on including a type declaration file, so TypeScript users can
import Eleventy from @11ty/eleventy
without gettingerror TS7016: Could not find a declaration file for module '@11ty/eleventy'.
?
No, sorry. Had mental health issues end of last year and then got carried away (in between Covid and everything).
No, sorry. Had mental health issues end of last year and then got carried away (in between Covid and everything).
Sorry to hear, and completely understandable -- it's been a hard few years for sure. No worries.
In case it's helpful to folks stumbling upon this thread, I was not interested in letting TypeScript transpile assets for the end user's browser, as we already use a bundler for that, but I was interested in having Eleventy code itself (config, and all the things (filters, shortcodes, helper functions) it imports, in TypeScript). For this we created a little wrapper .eleventy.js
config file with the following contents:
// @ts-check
// This is just a wrapper so we can have our real config in TypeScript.
require('ts-node').register({
files: true,
swc: true,
compilerOptions: {
module: 'commonjs',
},
})
// @ts-expect-error to avoid "An import path cannot end with a '.ts' extension. "
const { default: eleventyConfig } = require('./_eleventy/eleventyConfig.ts')
module.exports = eleventyConfig
You'll need at least yarn add --dev @swc/core ts-node typscript
for this to work.
From that moment on everything in _eleventy/
is in typescript. Adding swc
made it fast, there is no noticeable delay from live-transpiling like this, and not having build steps makes for a nice dx.
I added types by @chriskrycho which were linked higher up this thread and adjusted them a little bit to type the 11ty ts config and to give our code an understanding of what our collections are, etc.
It would certainly be cool if Eleventy at one point could natively load .eleventy.ts
if it existed and ts-node
happened to be installed. This is how Webpack (via node-interpret) and Jest do it as well, and I don't think it will be as invasive as other ways of supporting TypeScript on the consuming side. Although for us the difference would now just be deleting that 14 LoC JS wrapper file, so it really isn't the end of the world not having that.
I guess a bigger dent would be made if Eleventy provided also support for typescript data files, perhaps via https://github.com/11ty/eleventy/pull/2279, because this wrapper method gets unwieldy once we start it applying to dozens of files, and eleventyConfig.addDataExtension('ts')
can't be used because we don't have the path of the datafile, which will be important to resolve any imports if we want to transpile there.
JS wrapper file
One more downside of this approach where .eleventy.js
requires and transpiles an eleventyConfig.ts
, is that changes are no longer picked up by watch. So if you do end up making a config change, you have to restart Eleventy manually in order to see the impact on your build.
I don't think you can manually add more files, such as eleventyConfig.ts
, to the watch-list or can you? (google says no)
I don't think you can manually add more files, such as
eleventyConfig.ts
, to the watch-list or can you? (google says no)
I was wrong, I found addWatchTarget
and it works beautifully đ
In eleventyConfig.ts
:
// We wrap the eleventy typescript configuration in the original `.eleventy.js` file
// but that means any changes to the eleventy config aren't picked up, unless we add this:
eleventyConfig.addWatchTarget(__dirname)
// ^-- i keep the ts config in an `_eleventy` directory with more files that the config imports,
// but you may need to change this to `__filename` if it's just a lonely typescript file in the
// root for instance
Wanted to cross post this coming 2.0.0-canary.19 solution from @pspeter3 here https://www.11ty.dev/docs/languages/custom/#aliasing-an-existing-template-language
Relatedly, I have been merging a few types PRs for the Eleventy.js file and configuration files from folks recently into coreâappreciate help with those!
Tried that approach just now to get TS Data Cascade files but for me it ended in:
[11ty] Problem writing Eleventy templates: (more in DEBUG output)
[11ty] Youâre trying to use a layout that does not exist: console (undefined) (via Error)
[11ty]
[11ty] Original error stack trace: Error: Youâre trying to use a layout that does not exist: console (undefined)
[11ty] at TemplateLayoutPathResolver.getFullPath (/Users/kvz/code/content/node_modules/@11ty/eleventy/src/TemplateLayoutPathResolver.js:102:13)
[11ty] at new TemplateLayout (/Users/kvz/code/content/node_modules/@11ty/eleventy/src/TemplateLayout.js:22:7)
[11ty] at Function.getTemplate (/Users/kvz/code/content/node_modules/@11ty/eleventy/src/TemplateLayout.js:47:18)
[11ty] at Template.getLayout (/Users/kvz/code/content/node_modules/@11ty/eleventy/src/Template.js:127:37)
[11ty] at Template.getData (/Users/kvz/code/content/node_modules/@11ty/eleventy/src/Template.js:381:25)
[11ty] at async TemplateMap.add (/Users/kvz/code/content/node_modules/@11ty/eleventy/src/TemplateMap.js:64:16)
[11ty] at async Promise.all (index 1785)
[11ty] at async TemplateWriter._createTemplateMap (/Users/kvz/code/content/node_modules/@11ty/eleventy/src/TemplateWriter.js:257:5)
[11ty] at async TemplateWriter.generateTemplates (/Users/kvz/code/content/node_modules/@11ty/eleventy/src/TemplateWriter.js:294:5)
[11ty] at async TemplateWriter.write (/Users/kvz/code/content/node_modules/@11ty/eleventy/src/TemplateWriter.js:341:23)
That's on:
"@11ty/eleventy": "^2.0.0-canary.20",
"esbuild": "^0.16.10",
"esbuild-register": "^3.4.2",
"typescript": "^4.9.4",
Without the changes suggested by that Gist, it just works, the console
layout does exist.
Not sure what the best way to get more details on this error is
Tried that approach just now to get TS Data Cascade files but for me it ended in:
[11ty] Problem writing Eleventy templates: (more in DEBUG output) [11ty] Youâre trying to use a layout that does not exist: console (undefined) (via Error)
That's on:
"@11ty/eleventy": "^2.0.0-canary.20",
@kvz, either add a file extension for your template or bump Eleventy to "^2.0.0-canary.21"
; that should fix this.
See more info:
My third time looking at this, and finally, a simple end-to-end answer:
If you want:
Then do this:
"scripts": {
"dev": "node --require esbuild-register node_modules/.bin/eleventy --config=.eleventy.ts --serve",
"build": "node --require esbuild-register node_modules/.bin/eleventy --config=.eleventy.ts"
},
.eleventy.ts
// must be module.exports, not export defult.
module.exports = function (eleventyConfig: any) {
eleventyConfig.addExtension('11ty.tsx', {
key: '11ty.js',
});
// dev server doesn't spider js dependencies properly, so opt for hard browsersync with watch.
eleventyConfig.setServerOptions({
module: "@11ty/eleventy-server-browsersync",
snippet: true,
watch: true,
server: <your output folder>
});
}
tsconfig.json
{
"compilerOptions": {
"jsx": "react"
"jsxFactory": "h",
"jsxFragmentFactory": "h.Fragment",
}
}
src/pages/index.11ty.tsx
import h from 'vhtml';
export const data = {
title: 'Hello world',
};
export function render() {
return <h1>{data.title}</h1>;
}
run commands:
$ yarn add @11ty/eleventy @11ty/eleventy-server-browsersync esbuild esbuild-register vhtml @types/vhtml
yarn dev
Official template syntax docs for TypeScript and JSX just shipped here:
https://www.11ty.dev/docs/languages/typescript/ https://www.11ty.dev/docs/languages/jsx/
This also includes an approach to use TypeScript for your Eleventy configuration file too (as contributed by @danielrob above!)
Are there examples of how to use TypeScript with Eleventy?
Would like to be able to use TS with 11ty.