BETA

Clasp+TypeScriptで、stringにメソッドを追加拡張してみる

投稿日:2019-06-09
最終更新:2019-06-09
※この記事は外部サイト(https://qiita.com/yumechi/items/060969b7ac...)からのクロス投稿です

背景

ググラビティの問題からか、あまり類似した記事を見つけることができなかったので、記載してみようと思う。

以前こういう記事を書いた。

https://qiita.com/yumechi/items/9b4ce2d90165780d3243

しかし、このメソッドの2引数のとり方は違和感がある。

function startsWith(target, pattern) {  
  return target.indexOf(pattern) === 0;   
}  

引き渡す順序を覚えていないといけないし、変数自身に聞けばいいような問題に思われる。可能ならこう呼びたいはず。

stringItem.startsWith(pattern);  

もともとのプロジェクトを素のJavaScirptで書いていたのだが、TypeScript化するついでに、この問題を解決してみた。

調査: TypeString 自体に startsWith とかありそう?

なさそうだった。VSCodeで予測変換を噛ましてみたが、なさそうな感じだった。一応下記リンクとは一致していることを確認した。

TypeScript Strings - tutorialspoint

HandBookから探すのが難しい。どこを読むべきなんだろう。

microsoft/TypeScript-Handbook: The TypeScript Handbook is a comprehensive guide to the TypeScript language

Extension として書いたもの

参考にしたのは下記。

export {};  

/**  
 * String Extender  
 */  
declare global {  
  interface String {  
    /**  
     * Return True if string starts with the prefix, otherwise return False.  
     * @param word  
     */  
    startsWith(word: string): boolean;  
    /**  
     * Return True if string ends with the prefix, otherwise return False.  
     * @param word  
     */  
    endsWith(word: string): boolean;  
  }  
}  

String.prototype['startsWith'] = function(word: string) {  
  return this.indexOf(word) === 0;  
};  

String.prototype['endsWith'] = function(word: string) {  
  return (  
    this.lastIndexOf(word) + word.length === this.length &&  
    word.length <= this.length  
  );  
};  

吐き出されたコードはこんな感じ。

// Compiled using ts2gas 1.6.2 (TypeScript 3.5.1)  
var exports = exports || {};  
var module = module || { exports: exports };  
String.prototype['startsWith'] = function (word) {  
    return this.indexOf(word) === 0;  
};  
String.prototype['endsWith'] = function (word) {  
    return (this.lastIndexOf(word) + word.length === this.length &&  
        word.length <= this.length);  
};  

あ、メソッドの説明のところは Built-in Types Python 3.7.3 documentation の startsWith メソッドの部分 を参考にしている。(私は Python の人であるため)

これを他のファイルでインポートしてやるといい感じに動いた。

ハマったこと

下記のように書くと、this が捉えるスコープが広くなりすぎて( Logger を使って print してやると、なんかズラッとすべてのメソッド名なり、変数名なりが取れているので GAS 全体のオブジェクトが取れてそうな感じだった)思ったように動作しなかった。

調べてみるとアロー関数 - JavaScript | MDNがヒットしたので、読んでみると、「this を束縛しない」の章で納得。レキシカルスコープの this 値を使っているということで、理解した。

String.prototype.startsWith = (word: string): boolean => {  
  return this.indexOf(word) === 0;  
};  

吐き出されたコードがこれ。

// Compiled using ts2gas 1.6.2 (TypeScript 3.5.1)  
var exports = exports || {};  
var module = module || { exports: exports };  
var _this = this;  
String.prototype['startsWith'] = function (word) {  
    return _this.indexOf(word) === 0;  
};  
String.prototype['endsWith'] = function (word) {  
    return (_this.lastIndexOf(word) + word.length === _this.length &&  
        word.length <= _this.length);  
};  

実行してみると 実行に失敗: TypeError: オブジェクト [object Object] で関数 lastIndexOf が見つかりません。(行 9、ファイル「string.extensions」)(合計ランタイム 0.382 秒)

つまりそうなる。はい。

感想

できるだろう…! と思ったが、実現するまでに時間がかかりすぎてしまった。 prototype に突っ込むとか、アロー関数と function の違いとか、ちょっと驚くこともあったが、実現できるということがわかったので学びがあってよかった。

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

技術ブログとは何なのだろう。なんかちょっと試してみたものをメモがてら残してみています。

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!