2019/11 TypeScriptで気に入ってるちょっといいところ

佐々木誠

TypeScriptはMicrosoftが開発しているJavaScriptベースなプログラミング言語です。 いわゆるAltJSで型のあるJSというところですが、型があるというとJavaかな?え、面倒くさい!と誤解されたり身構えられることがあります。 そこで今回は、厳格さと柔軟さをほどよく兼ね備えたTypeScriptをサンプルコードで紹介します。

型構文

まずは基本的な型の指定方法です。

// 変数の前ではなく、後ろにコロン&型(この場合string)指定
const word: string = 'hello world';

// 独自の型も作れる(この場合Markという独自の型)
type Mark = {
  question: boolean,
  exclamation: boolean,
  advance: string
};

// 括弧の中が引数、括弧の後ろのコロン&型が戻り値の型
function addTimestamp(msg:string, time:number, option:Mark): string{

  let ret = `${msg}_${time}`;

  if(option.question){
    ret += '!';
  }
  if(option.exclamation){
    ret += '?';
  }
  if(option.advance){
    ret += advance;
  }

  return ret;
}

CやJavaと違い、golangやRustのように型は後ろに指定するスタイルです。 最初は戸惑うかもしれませんが慣れます。

また、わざわざクラス定義しなくてもtypeで純粋にデータの型だけ作れるので、カジュアルに型宣言できストレスなくコーディングできますね。

関数コール

上記のaddTimestamp関数の利用例です。

const data:Mark = {
  question: true,
  exclamation: false,
  advance: '!!'
};

const msg:string = addTimestamp('hello', 12345, data);

TypeScriptには型推論が備わっているため以下のように書くこともできます。

const data = {
  question: true,
  exclamation: false,
  advance: '!!'
};

const msg = addTimestamp('hello', 12345, data);

このようにdata:Markmsg:stringの型記述を省略できます。 これはdataaddTimestampの第3引数なのでMark型であることが自明である。msgaddTimestampの戻り値なのでstring型であることが自明であるためです。 もし違う型だった場合は、VSCode上 or ビルド時にちゃんと指摘してくれます。

このように型推論のおかげで、一般的な静的言語より煩わしさが減りスクリプト言語のような手軽さを実感していただけると思います。

柔軟編

型推論 代入編

先程紹介した型推論ですが、変数宣言時にも活躍します。

const msg: string = 'hello';
const time: number = 1234;
const done: boolean = false;

↓↓↓

const msg = 'hello';
const time = 1234;
const done = false;

代入された値から、変数の型は自明なので省略できます。

関数

type Position = {
  x: number,
  y: number
};
function movePoint(point: Position): void{
  // etc...
}

↓↓↓

function movePoint(point: {x: number, y: number}): void{
  // etc...
}

引数pointの型を独自型Positionと宣言しなくても、直接オブジェクト型で指定することもできます。 色んなところから呼ばれる関数なら明確にPositionのようにしたほうがいいですが、private関数のような感じでちょっと使われるだけの関数の場合に活用するとよいでしょう。 仕様変更・追加していくなかで巨大な関数に成長しリファクタリングしたくなったとき、気軽に関数を分割できるのでとても役立ちます。

複数型指定

function moveX(x: number | string): void{
  let point = 0;
  if(x instanceof number){
    point = x;
  }else if(x instanceof string){
    point = Number(x);
  }
  // etc...
}

union型と言われるものですが、|で引数の型をnumberstringの両方を受け付けることができます。 積極的に使うものではありませんが、既存からの移行時などどうしても仕方なく。。。といった場合に利用すると良いでしょう。

any編

void hoge(data: any){
  console.log(data.foo);
}

できるだけ使わないほうがいいのですが、anyというJSのように何にでもなれる型もあります。 使ったら負け感はありますが、こちらも既存からの移行時など仕方なく利用することもできます。

ローカル変数の可読性を上げる

ちょっと型からは脱線するのですが、JS・TypeScriptでのテクニックをご紹介します。

const imageWidth = 123;
const imageHeight = 999;
const imageScale = 0.9;
const userName = 'Jon';
const userAge = 28;
const userLocationHome = 'saitama';
const userLocationOffice = 'chiyoda';

↓↓↓

const image = {
  width: 123,
  height: 999,
  scale: 0.9
};
const user = {
  name: 'Jon',
  age: 28,
  location: {
    home: 'saitame',
    office: 'chiyoda'
  }
};

データを受け取ったときなどに素直に1変数づつ代入することが一般的ですが、このようにオブジェクト型で分類すると一気に可読性が上がります。上記の宣言時だけでなく、以降の実際の処理で変数を利用するとき、処理(関数)が長く複雑になっても可読性をキープできるのでおすすめです。

以上、TypeScriptの型について紹介しました。今までのプログラミング言語より記述量少なく手軽にコーディングできることがわかっていただけたと思います。

こんな記事も読まれています