Typescript で 型の import 文を減らす方法・滅す方法

# 型importとは

Typescriptで、型情報を使用するためにimport/fromしている箇所をそう呼んでいます:santa:

```User.ts

export interface User{
 name: string;
 age: number;
}
```

```sample.ts
import { User } from "./User" // 型import

const user = http<User>(url, option)
```

いまはひとつだけだからいいのですが、型安全にしていくと
レスポンスをするための型importや、マテリアルデザインの型情報、などimportが積もっていきます。
型のimport自体は、Typescriptでしか必要ありません。

# 結論

1. interface をまとめた ファイル を用意（減らす）
2. declare global 宣言を使用（滅す）

「減らす」と「滅す」は漢字似てるけど大違い:santa:

# 背景

例えば、webpack.config.jsをTypescriptで書こうとすると、下記の型import量になります（sassやfiber入れるともっと増えます）

```webpack.config.ts
import { join, resolve } from 'path';
import { env } from 'process';
import { Configuration, HotModuleReplacementPlugin, ProvidePlugin } from 'webpack'; // 3分の1型
import { Configuration as DevServerConfig } from 'webpack-dev-server'; // 型
type NODE_ENV = 'development' | 'production' | 'none'; // 型

const { NODE_ENV } = env;

const config: Configuration & DevServerConfig = {
  mode: NODE_ENV as NODE_ENV,

  ~~ 省略 ~~
```

~~ReactでMaterial-UIとか使うと、ファイルのファーストプレビューのほぼimport文やで！！！~~



interface や、class、返却値の型アサーションなど、「型のための import 文」を減らしたい。
型importはまた別のところでのさばってしまう！

# 動機

「型の import」って、「読む」ときは都合よく非表示ならんかな（ならない）
省略していいのでは（いや、省略できるはずだ）
書くのは1回で終わりたい！

# [お館さま](https://typescript-jp.gitbook.io/deep-dive/)に聞いてみよう

型 import のことは私が容認していた。みんなにも認めてもらいたいと思っている。

# しかし・・・

コードはコードです。
長くて、読むに値しないコードはすべて省略対象かと！

# 鬼の対義語があるとしたら、それはお館さま

そうだね。ただ・・・やるとしたら

> ファイルモジュールを使うことを強くお勧めします。

御意orz（否定せず道を指し示してくれる姿勢涙）

参照：[globals.d.ts](https://typescript-jp.gitbook.io/deep-dive/project/modules/globals)

## 【考えその1】お館様の望むままに従います 
### → interface の呼吸・型のわななき

ファイルモジュールの方式

## 【考えその2】心より尊敬するお館さまであるが、理解できない考えだ。全力で反対する！ 

### → 「declare global の呼吸・型輸入全焼却滅」

型のimportは不要になります。



自分は「型輸入全焼却滅」をしましたが、[お館さま](https://typescript-jp.gitbook.io/deep-dive/)は型の ファイルモジュールの方式 を推奨をしているようです。

# ようやく詳細

## interface の呼吸・型のわななき

ファイルモジュールにサンプルがないのですが、きっとimport/exportを用いた方法のことでしょう。
そして、型をexportするにはいろいろ方法があり、type aliasも手ですが、ここではinterfaceを用います。
interfaceはtype aliasもねじれ渦🌀のように巻き込めます


### やること

1. definition.ts（ファイル名はなんでもよいです）を用意
2. definition.tsにinterfaceを記述して、key/valueを用意
3. import先でkeyを指定する（例：`WebpackConfig['config']`）

```definition.ts
import { Configuration } from 'webpack';
import { Configuration as DevServerConfig } from 'webpack-dev-server';
type NODE_ENV = 'development' | 'production' | 'none';

export interface WebpackConfig {
  config: Configuration;
  devServerConfig: DevServerConfig;
  NODE_ENV: NODE_ENV;
}
```

```webpack.config.ts
import { join, resolve } from 'path';
import { env } from 'process';
import { HotModuleReplacementPlugin, ProvidePlugin } from 'webpack';
import { WebpackConfig } from './definition'; // 追加

const { NODE_ENV } = env;

const config: WebpackConfig['config'] & WebpackConfig['devServerConfig'] = { // 変更
  mode: NODE_ENV as WebpackConfig['NODE_ENV'], // 変更

  ~~ 省略 ~~
```

ひとつのimport文で必要なkey名を指定するパターンですね！
いろんなライブラリーがとっている手段ですね！

ただ、configに当てた型を見てください！

```webpack.config.ts
const config: WebpackConfig['config'] & WebpackConfig['devServerConfig'] = { // 変更
```

型が冗長になりがちですね!
これはなんという型だ！？

[Static types for dynamically named properties](https://github.com/Microsoft/TypeScript/pull/11929)という異国の名だと！
長い！



## declare global の呼吸・型輸入全焼却滅



### やること

1. definition.ts（ファイル名はなんでもよい！馬の骨でもいい！）を用意する
2. `declare global`を用意して、key/valueをつくる

```definition.ts
import { Configuration } from 'webpack'; // 型
import { Configuration as DevServerConfig } from 'webpack-dev-server'; // 型
type NODE_ENV = 'development' | 'production' | 'none'; // 型

declare global {
  type webpackConfig = Configuration;
  type devServerConfig = DevServerConfig;
  type nodeEnv = NODE_ENV;
}
```

```webpack.config.ts
import { join, resolve } from 'path';
import { env } from 'process';
import { HotModuleReplacementPlugin, ProvidePlugin } from 'webpack';

const { NODE_ENV } = env;

const config: webpackConfig & devServerConfig = { // 変更
  mode: NODE_ENV as nodeEnv, // 変更
```

ほとんど、`interface の呼吸・型のわななき`とやっていることはほぼ変わらない！?
ですが、configの型をみてください

```webpack.config.ts
const config: webpackConfig & devServerConfig = { // 変更
```

重複した箇所も消えて、とても読みやすくなってます！おまけに`webpack.config.ts`から型のimport文を滅すことができました！

しかし、よく調教されたJS・TS使いは`global`という言葉にとても敏感じゃ。
本当の本当にglobalを使っていいんですか？

もし型の名称の衝突が起こった時は、鎹鴉（VSCode）が知らせてくれるので大丈夫だと思います。

というか、Typescriptは鎹鴉（VSCode）頼みです。

たとえ、VSCodeがFinalCutPro並みの金額だろうと買うと思います（経費で）

# まとめ

- 型のimport文を減らすには、ファイルモジュールを使う（型のわななきの方）←TypeScript Deep Dive 推奨
- 型のimport文を滅すには、`global declare`を使用（型輸入全焼却滅の方）

# おわりに

あぁー鬼滅要素いれて、ややこしくしてしまった気が:santa:

# 参照

- [TypeScript Deep Dive 日本語版](https://typescript-jp.gitbook.io/deep-dive/)