TypeScript + Webpackのハマったところメモ

不親切なメモです。

Typingsのinstallでエラー

このテンプレコマンドを使うと
typings install jquery --save --ambient

こんなエラーが出る:
The "ambient" flag is deprecated. Please use "global" instead

コマンドを変更:
typings install dt~jquery --save --global

ambientをglobalにしてモジュールの頭にdt~をつける。

私のMacだとこれじゃないとだめだった:
sudo $(npm bin)/typings install dt~jquery --save --global

Gulpでwebpackのwatchかけてたらエラーで怒られた件

(node) warning: possible EventEmitter memory leak detected. 11 reset listeners added. Use emitter.setMaxListeners() to increase limit.

その時書いてたタスク:

1
2
3
4
5
6
7
8
9
10
gulp.task('js', function(){
  return gulp.src(["src/**/*.ts",'!' + "src/**/_*.ts"],{base: 'src'})
  .pipe(webpack( require('./webpack.config.js') ))
  .pipe(gulp.dest('public'));
});
 
gulp.task('watch', function () {
  gulp.watch(['src/**/*.scss', 'src/**/*.ejs'], ['css', 'html']);
  gulp.watch(["src/**/*.ts",'!' + "src/**/_*.ts"], ['js']);
});

この書き方だとtsファイルが変更されるたびにwebpackが増えて最終的に爆発するのだった。

gulpでwatchは止める。

1
2
3
gulp.task('watch', function () {
  gulp.watch(['src/**/*.scss', 'src/**/*.ejs'], ['css', 'html']);
});

代わりにwebpack.config.jsにwatchを追加する:

1
2
3
{
  watch: true
}

typingsの操作をしようとしたらPermissionで怒られる

所有者をrootから自分に変更する:

$ sudo chown USERNAME typings
$ sudo chown USERNAME typings.json

typings install できるライブラリが npm install に未対応

CreateJSがこのケースだった。
cdnへのリンクじゃなくてファイル1つにまとめたい場合に。

npm install対応しているjQueryなんかは、

1
import 'jquery';

これでnode_moudlesから読み込んでくれるから楽なんだけれども…
対応してないものに関してはこの手が使えないのであった。

typings installで型定義をインストールした後に、
ライブラリをダウンロードして適当な場所に展開したものをimoortする。

1
2
/// <reference path="../../../../../typings/index.d.ts" />
import '../EaselJS-0.8.2/lib/easeljs-0.8.2.combined.js';

TypeScriptでjQueryのライブラリimportしたらエラーが出る件

まずjQueryプラグイン定番のおまじないをCommonJSやAMDに対応させる:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//定番のbefore
(function($) {
    $.fn.myPlugin = function (option, action) {
     
    };
}(jQuery));
 
//after
(function(factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory(require('jquery'));
    } else {
        factory(jQuery);
    }
}(function($) {
    $.fn.myPlugin = function (option, action) {
     
    };
}));

手書きでTypeingsを追加する:

1
2
3
4
5
6
7
8
//typings/myplugin/index.d.ts
interface JQueryMyPluginOptions {
}
 
interface JQuery {
    myPlugin(): JQuery;
    myPlugin(options: JQueryMyPluginOptions): JQuery;
}
1
2
//typings/index.d.ts
/// <reference path="myplugin/index.d.ts" />

windowなどのオブジェクトに定義されてないプロパティやメソッドを追加すると怒られる件

例えばYoutubeのiFrameAPIのwindow.onYouTubeIframeAPIReadyみたいな
windowに追加されるメソッドを直接叩かなければならないような時、そのまま書くと

error TS2339: Property 'onYouTubeIframeAPIReady' does not exist on type 'Window'.

って怒られるんで、typingsの要領で定義する:

1
2
3
4
5
6
7
8
9
10
11
  interface Window {
      onYouTubeIframeAPIReady(): void;
  }
  declare var window: Window;
 
//または
 
  interface MyWindow extends Window {
      onYouTubeIframeAPIReady(): void;
  }
  declare var window: MyWindow;

Typingsの書き方

newするやつ:

1
2
3
4
5
declare class MyClass {
    constructor( options: any );
    foo(): void;
    bar( from: number, hoge?: boolean): void;
}

newしないやつ:

1
2
3
4
interface Hoge {
    foo: Bar;
}
declare var Hoge:Hoge;

namespaceがあるやつ:

1
2
3
4
5
declare namespace myNamespace {
    export class myClass {
    }
    export function myFunc() : any;
}

jQueryプラグイン:

1
2
3
4
5
6
7
interface JQueryMyPluginOptions {
}
 
interface JQuery {
    myPlugin(): JQuery;
    myPlugin(options: JQueryMyPluginOptions): JQuery;
}

Object/Enumのkeyに変数でアクセスしたら怒られる

オプションのnoImplicitAnyをtrueにしてたら怒られるわけだが、そうは言ってもよく使うじゃん。

1
2
3
4
5
6
7
8
9
10
11
  let Foo = {
    bar: 'hoge'
  };
 
  let bar = 'bar';
 
  console.log(Foo['bar']); //怒られない
  console.log(Foo[bar]); //怒られる
//Index signature of object type implicitly has an 'any' type.
 
  (<any>Foo)[bar]; //怒られない
1
2
3
4
5
6
7
8
9
10
11
12
enum Hoge {
  bar
}
 
console.log(Hoge.bar); //怒られない
console.log(Hoge[bar]); //怒られる
//Element implicitly has an 'any' type because index expression is not of type 'number'.
 
console.log((<any>Hoge)[bar]);//怒られない
 
let Hoge2: { [idx: string]: Hoge; } = <any>Hoge;
console.log(Hoge2[bar]); //怒られない

interfaceを使う

1
2
3
4
5
6
7
8
9
  interface HogeInterface {
    bar: string,
    [key: string]: string
  };
let Hoge: HogeInterface = {
   bar: 'hoge'
};
let bar = 'bar';
console.log(Foo[bar]);

他には noImplicitAny: false にするなど。

Webpackで端末毎にファイルを分けて出力したい

※Typescript関係ない

PC版とSP版でbundleされるファイルを分けないとアカン……
せや!nameにディレクトリ追加したろ!

1
2
3
4
5
6
7
8
9
10
11
entry: {
  'pc/assets/js/common': './src/pc/assets/js/common.ts',
  'pc/assets/js/top': './src/pc/assets/js/top.ts',
 
  'sp/assets/js/common': './src/sp/assets/js/common.ts',
  'sp/assets/js/top': './src/sp/assets/js/top.ts'
},
 
output: {
  filename: "[name].js",
},

CommonsChunkPluginは複数設定できる

出力ファイルが分かれるならCommonsChunkPluginも分けたい奴ごとに設定しておく。

1
2
3
4
5
6
7
8
9
10
plugins: [
      new webpack.optimize.CommonsChunkPlugin({
          name: 'pc/assets/js/common',
          chunks: ['pc/assets/js/top']
      }),
      new webpack.optimize.CommonsChunkPlugin({
          name: 'sp/assets/js/common',
          chunks: ['sp/assets/js/top']
      })
]

コメントを残す

This site uses Akismet to reduce spam. Learn how your comment data is processed.