型importとは
Typescriptで、型情報を使用するためにimport/fromしている箇所をそう呼んでいます
export interface User{
name: string;
age: number;
}
import { User } from "./User" // 型import
const user = http<User>(url, option)
いまはひとつだけだからいいのですが、型安全にしていくと
レスポンスをするための型importや、マテリアルデザインの型情報、などimportが積もっていきます。
型のimport自体は、Typescriptでしか必要ありません。
結論
- interface をまとめた ファイル を用意(減らす)
- declare global 宣言を使用(滅す)
「減らす」と「滅す」は漢字似てるけど大違い
背景
例えば、webpack.config.jsをTypescriptで書こうとすると、下記の型import量になります(sassやfiber入れるともっと増えます)
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回で終わりたい!
お館さまに聞いてみよう
型 import のことは私が容認していた。みんなにも認めてもらいたいと思っている。
しかし・・・
コードはコードです。
長くて、読むに値しないコードはすべて省略対象かと!
鬼の対義語があるとしたら、それはお館さま
そうだね。ただ・・・やるとしたら
ファイルモジュールを使うことを強くお勧めします。
御意orz(否定せず道を指し示してくれる姿勢涙)
参照:globals.d.ts
【考えその1】お館様の望むままに従います
→ interface の呼吸・型のわななき
ファイルモジュールの方式
【考えその2】心より尊敬するお館さまであるが、理解できない考えだ。全力で反対する!
→ 「declare global の呼吸・型輸入全焼却滅」
型のimportは不要になります。
自分は「型輸入全焼却滅」をしましたが、お館さまは型の ファイルモジュールの方式 を推奨をしているようです。
ようやく詳細
interface の呼吸・型のわななき
ファイルモジュールにサンプルがないのですが、きっとimport/exportを用いた方法のことでしょう。
そして、型をexportするにはいろいろ方法があり、type aliasも手ですが、ここではinterfaceを用います。
interfaceはtype aliasもねじれ渦🌀のように巻き込めます
やること
- definition.ts(ファイル名はなんでもよいです)を用意
- definition.tsにinterfaceを記述して、key/valueを用意
- import先でkeyを指定する(例:
WebpackConfig['config']
)
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;
}
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に当てた型を見てください!
const config: WebpackConfig['config'] & WebpackConfig['devServerConfig'] = { // 変更
型が冗長になりがちですね!
これはなんという型だ!?
Static types for dynamically named propertiesという異国の名だと!
長い!
declare global の呼吸・型輸入全焼却滅
やること
- definition.ts(ファイル名はなんでもよい!馬の骨でもいい!)を用意する
-
declare global
を用意して、key/valueをつくる
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;
}
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の型をみてください
const config: webpackConfig & devServerConfig = { // 変更
重複した箇所も消えて、とても読みやすくなってます!おまけにwebpack.config.ts
から型のimport文を滅すことができました!
しかし、よく調教されたJS・TS使いはglobal
という言葉にとても敏感じゃ。
本当の本当にglobalを使っていいんですか?
もし型の名称の衝突が起こった時は、鎹鴉(VSCode)が知らせてくれるので大丈夫だと思います。
というか、Typescriptは鎹鴉(VSCode)頼みです。
たとえ、VSCodeがFinalCutPro並みの金額だろうと買うと思います(経費で)
まとめ
- 型のimport文を減らすには、ファイルモジュールを使う(型のわななきの方)←TypeScript Deep Dive 推奨
- 型のimport文を滅すには、
global declare
を使用(型輸入全焼却滅の方)
おわりに
あぁー鬼滅要素いれて、ややこしくしてしまった気が