I'm exporting my design tokens as ES6 modules and I'm having troubles figuring out a way to type these. Currently, I type them with a module.d.ts file as such:
tokens.js
export const ColorWhite = "#ffffff";
export const ColorBlack = "#222222";
...
module.d.ts
declare module 'design-tokens' {
export const ColorWhite: string;
export const ColorBlack:string;
...
}
As the tokens are generated automatically and a lot of tokens will be added in the future it's kinda tedious. I haven't seen a way to export type declarations atm and also this issue doesn't appear to cover my use case.
Has anyone had the same problem and knows a way around it?
Maybe there is a TypeScript way of declaring the module's exports dynamically? I'm thinking something like this:
declare module 'design-tokens' {
export const [token]: string;
}
I'm handling this through a template like this
src/templates/typings/es6.template for exampleThink of replacing the module name to reflect the real name of your module.
/**
* Do not edit directly
* Generated on <%= new Date().toUTCString() %>
*/
declare module 'design-tokens' {
<% _.each(allProperties, function(property) {
%> export const <%= property.name %>: string;
<% }); %>
}
build.jsconst _ = require('lodash');
const fs = require('fs');
const StyleDictionary = require('style-dictionary').extend('./config.json');
const typingsES6Template = _.template(
fs.readFileSync(`${__dirname}/src/templates/typings/es6.template`)
);
StyleDictionary.registerFormat({
name: 'typings/es6',
formatter: typingsES6Template,
});
StyleDictionary.buildAllPlatforms();
config.jsonYou can use any platform name, and destination for this
{
"source": ["src/**/*.json"],
"platforms": {
"js": {
"transformGroup": "js",
"buildPath": "dist/",
"files": [
{
"destination": "index.js",
"format": "javascript/es6"
}
]
},
"ts": {
"transformGroup": "js",
"buildPath": "dist/",
"files": [
{
"destination": "index.d.ts",
"format": "typings/es6"
}
]
},
}
}
Result
import { ColorWhite } from 'design-tokens'; // <--- No TS errors.
Hope this helps
As an alternative, you can also generate .ts files. Since typescript can infer simple types this should be enough to import constants without ts errors.
It's true, that was my first idea but I was in favor of not adding typescript deps + logic for this.
Also this method will help other developers to type the other js output such as the javascript/module for example
Most helpful comment
I'm handling this through a template like this
src/templates/typings/es6.templatefor examplebuild.jsconfig.jsonResult
Hope this helps