webpack-typings-for-json
Version:
Webpack loader that generates TypeScript typings for JSON files
245 lines (201 loc) • 6.93 kB
Markdown
# Webpack typings for JSON loader
[![NPM][npm-image]][npm-url]
[![License][license-image]][license-url]
[![Coverage][coverage-image]][coverage-url]
[![Downloads][downloads-image]][downloads-url]
[![Build][build-image]][build-url]
> Webpack loader that generates TypeScript typings for JSON files
## Installation
```
npm install webpack-typings-for-json --save-dev
```
**webpack.config.js**
```javascript
module.exports = {
module: {
rules: [{
test: /\.json$/,
type: 'javascript/auto',
use: [{
loader: 'webpack-typings-for-json'
}]
}]
}
};
```
## Example (i18n)
Let's say our project uses a JSON based localization setup, like [i18next](https://www.i18next.com/)
and we have the following file: `./src/locale/en.js` in your project, containing the following
(simple) resource strings:
```json
{
"align-left": "Align left",
"align-center": "Align centre",
"align-right": "Align right",
"justify": "Justify",
"bullet-list": "Bullet list",
"numbered-list": "Numbered list",
"decrease-indent": "Decrease indent",
"increase-indent": "Increase indent"
}
```
When we add the `webpack-typings-for-json` loader, this will generate a TypeScript
definition file `./src/locale/en.d.ts` with the following content:
```typescript
declare const locale = {
alignLeft: 'align-left',
alignCenter: 'align-center',
alignRight: 'align-right',
justify: 'justify',
bulletList: 'bullet-list',
numberedList: 'numbered-list',
decreaseIndent: 'decrease-indent',
increaseIndent: 'increase-indent'
} as const;
export type LocaleKey = string;
export default locale;
```
In your Typescript file you will now be able to import this localization
file and get type hints with the available properties. The values for
these properties are the keys of the original json:
```typescript
import locale from './en.json';
console.log(locale.alignLeft); // "align-left"
console.log(locale.alignRight); // "align-right"
console.log(locale.alignCenter); // "align-center"
console.log(locale.justify); // "justify"
```
In your (React) component you can import this localization file and use
the properties as input for the translation function / library to fetch the
right string. This means: **No more hard coded keys. And if someone changes
the JSON, you will get compile time warnings!**
```typescript jsx
import React from 'react';
import { useTranslation } from 'react-i18next';
import locale from './en.json';
export const MyComponent = () => {
const { t } = useTranslation();
return (
<div>
<span>{t(locale.alignLeft)}</span>
<span>{t(locale.alignRight)}</span>
<span>{t(locale.alignCenter)}</span>
<span>{t(locale.justify)}</span>
</div>
);
};
```
## Example (properties)
Some projects use a JSON file as a 'configuration' or 'settings' file that specifies build
properties. For instance: A location to a server, some theme settings, etc. We normally embed
these properties during build time (using Webpack), but they are never typed... You can use
this same loader to generate typings for this JSON file and use the values, as if you
are using a normal Typescript object.
Let's say you have the following settings file `./src/settings.json`:
```json
{
"server": "https://github.com",
"username": "John Doe",
"theme": {
"color": "#FF0000",
"fonts": {
"header": "{ font-family: monospace; font-size: 20px; }",
"body": "{ font-family: monospace; font-size: 12px; }"
}
}
}
```
When we add the `webpack-typings-for-json` loader, then we can specify
the option to include the values, rather then the keys in the output
object:
**webpack.config.js**
```javascript
module.exports = {
module: {
rules: [{
test: /\.json$/,
type: 'javascript/auto',
use: [{
loader: 'webpack-typings-for-json',
options: {
exportValues: true
}
}]
}]
}
};
```
this will generate a TypeScript definition file `./src/settings.json.d.ts` with
the following content, as you can see this is just a normal Typescript interface
that matches the JSON we are importing:
```typescript
const locale = {
server: 'https://github.com',
username: 'John Doe',
theme: {
color: '#FF0000',
fonts: {
header: '{ font-family: monospace; font-size: 20px; }',
body: '{ font-family: monospace; font-size: 12px; }'
}
}
} as const;
export type LocaleKey = string;
export default locale;
```
In your Typescript file you will now be able to import this settings
file and get type hints with the available properties. The values for
these properties are directly coming from the imported json
```typescript
import settings from './settings.json';
console.log(settings.server); // https://github.com
console.log(settings.username); // John Doe
console.log(settings.theme.color); // #FF0000
console.log(settings.theme.fonts.header); // { font-family: monospace; font-size: 20px; }
console.log(settings.theme.fonts.body); // { font-family: monospace; font-size: 12px; }
```
## Known issues
As the loader generates typing files, it is wise to tell webpack to ignore them.
The fix is luckily very simple. Webpack ships with a "WatchIgnorePlugin" out of the box.
Simply add this to your webpack plugins:
```javascript
plugins: [
new webpack.WatchIgnorePlugin([
/json\.d\.ts$/
]),
...
]
```
You might see project warnings when you have not yet build the project. This happens
because Typescript cannot import JSON files (since they are not official modules).
In order to fix this you can add a type definition to your project:
**./typings/json.d.ts**
```typescript
declare module '*.json' {
declare const keys: {
readonly [key: string]: string;
};
export type LocaleKey = string;
export default keys;
}
```
**tsconfig.json**
```json
{
...
"files": [
"./typings/json.d.ts"
],
...
}
```
[npm-url]: https://npmjs.org/package/webpack-typings-for-json
[npm-image]: https://img.shields.io/npm/v/webpack-typings-for-json.svg
[license-url]: LICENSE
[license-image]: http://img.shields.io/npm/l/webpack-typings-for-json.svg
[coverage-url]: https://codecov.io/gh/ferdikoomen/webpack-typings-for-json
[coverage-image]: https://img.shields.io/codecov/c/github/ferdikoomen/webpack-typings-for-json.svg
[downloads-url]: http://npm-stat.com/charts.html?package=webpack-typings-for-json
[downloads-image]: http://img.shields.io/npm/dm/webpack-typings-for-json.svg
[build-url]: https://circleci.com/gh/ferdikoomen/webpack-typings-for-json/tree/master
[build-image]: https://circleci.com/gh/ferdikoomen/webpack-typings-for-json/tree/master.svg?style=svg