LoginSignup
11
6

More than 3 years have passed since last update.

webpack.config.jsで補完を効くようにする

Last updated at Posted at 2019-05-09

※vscodeでの開発が前提です

TL;DR

webpack.config.js
const webpack = require("webpack")

/** @type {Parameters<typeof webpack>[0][0]} */
const config = {
  // ...
}

module.exports = config

スクリーンショット 2019-05-09 14.29.54.png

こんな感じ (jsdocの中身がキモい。。)

補足

型が正しく表示されない場合、以下のコマンドを実行してください

npm i -D @types/webpack

vscodeのデフォルトの設定では、package.jsonから自動的に型定義ライブラリをインストールしてくれます。

(@elastic氏のコメントより)

解説

@types/webpackには以下のように定義されています。(一部略)

export = webpack;

declare function webpack(
    options: webpack.Configuration,
    handler: webpack.Compiler.Handler
): webpack.Compiler.Watching | webpack.Compiler;
declare function webpack(options?: webpack.Configuration): webpack.Compiler;

declare function webpack(
    options: webpack.Configuration[],
    handler: webpack.MultiCompiler.Handler
): webpack.MultiWatching | webpack.MultiCompiler;
declare function webpack(options: webpack.Configuration[]): webpack.MultiCompiler;

declare namespace webpack {
    interface Configuration {
        // ...
    }
}

webpack.Configurationが webpack.config.jsでexportする型です。

tsならば、以下のようにかけます。

import webpack, { Configuration } from "webpack"

const config: Configuration = {
  // ...
}

export = config

しかし、webpack.Configurationをjs上でimportすることはできません。 追記参照

色々試した結果、webpack関数の引数からConfiguration型の情報を取るという回りくどいやり方でできました。

tsでは、Parametersという関数から引数の型の情報を取得する組み込み型があります。

lib.es5.d.ts
/**
 * Obtain the parameters of a function type in a tuple
 */
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
// 使用例
// Params1, Params2は [number, string] 型になる
type Callback = (a: number, b: string) => void
type Params1 = Parameters<Callback>

function func(a: number, b: string) {}
type Params2 = Parameters<typeof func>

Parametersを使用し、webpack関数からConfiguration型を取るのをtsで書いてみます。

vscodeにコピペすれば型情報が見れます。

import webpack from "webpack"

type Webpack = typeof webpack
/*
型 → {
  (options: webpack.Configuration, handler: webpack.Compiler.Handler):
    | webpack.Compiler.Watching
    | webpack.Compiler
  (options?: webpack.Configuration): webpack.Compiler

  (options: webpack.Configuration[], handler: webpack.MultiCompiler.Handler):
    | webpack.MultiWatching
    | webpack.MultiCompiler
  (options: webpack.Configuration[]): webpack.MultiCompiler
  ...
}
*/

type WebpackParameters = Parameters<Webpack>
/*
型→ [webpack.Configuration[]]
*/

type Param = WebpackParameters[0]
/*
型→ webpack.Configuration[]
*/

type Config = Param[number]
/*
型→ webpack.Configuration
*/

この型定義をワンランナーにしてさらに短くすると

import webpack from "webpack"

type Config = Parameters<typeof webpack>[0][0]

これをjsdocの@typeに記述すればokです!

余談

webpack環境を一から構築しようとした副産物でこれができたのですが、肝心のwebpackは複雑すぎてまだ使用できていません😭

2019/5/10 追記

webpack.config.js
/** @typedef {import('webpack').Configuration} WebpackConfiguration */

/** @type WebpackConfiguration */
const config = {
  // ...
}

@elastic氏のコメントより、これでもいけるそうな

こっちの方がわかりやすくていいですね(でもやっぱりjsdocの中身がキモい。。)

また、jsdocの@typedefは初見だったので、知れて良かったです。

@elastic氏、ありがとうございます!

2019/5/13 追記2

webpack.config.jsをtsで記述するというやり方を叶えてくれる記事を見つけたのでリンクを貼っておきます。

@sprout2000氏、ありがとうございます!

11
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6