4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

TypeScriptの型づけを使う ー Union型、列挙型、型の別名など

Last updated at Posted at 2017-02-01

TypeScriptには、JavaScriptに備わるデータ型だけでなく、ECMAScript 2015の仕様も採り入れて、型や機能が加えられています。それらを試してみましょう。なお、TypeScriptの型づけの基本については、「TypeScript: 基本型」をお読みください。

01 カラー整数値からRGBカラー成分値を配列で返す関数

以下のコード001(TypeScriptサイトのPlaygroundにリンクしています)は、引数に渡したRGBカラーの整数値からRGBごとの成分値を配列で返す関数です。関数は、つぎのように試すことができます。なお、カラー整数値からRGBカラー成分値を求めるビット演算については、「2進数・16進数とビット演算」05「カラー値とビット演算」をお読みください。

let components: number[] = getColorComponents(0xFFCC99);
console.log(components);  //  [ 255, 204, 153 ]
console.log(components[0].toString(16), components[1].toString(16), components[2].toString(16));
// ff cc 99

コード001

function getColorComponents(color: number): number[] {
     let red : number = color >> 16;
     let green: number = color >> 8 & 0xFF;
     let blue: number = color & 0xFF;
     return [red, green, blue];
}

02 戻り値を配列とオブジェクトから選べるようにする

戻り値をオブジェクトで受け取ることもできるようにします。配列かオブジェクトかは、つぎのように関数にブーリアン(論理)値の第2引数を加えて選びます。戻り値がひとつの型に定まりませんので、以下のコード002はとりあえずanyで型づけしました。

let components = getColorComponents(0xFFCC99, false);
console.log(components);  // { red: 255, green: 204, blue: 153 }

コード002

function getColorComponents(color: number, array: boolean): any {
	let red : number = color >> 16;
	let green: number = color >> 8 & 0xFF;
	let blue: number = color & 0xFF;
	if (array) {
		return [red, green, blue];
	} else {
		return {red: red, green: green, blue: blue};
	}
}

03 戻り値に納める値もふたつ選べるようにする

カラー値を16進数表記で知りたい場合もあります。数値では表せませんので、文字列を用いることにします。そのため、関数にブーリアン値の第3引数を加えます。以下のコード003はUnion型|により、変数に数値(number )か文字(string )という型づけをしました。

let components = getColorComponents(0xFFCC99, false, true);
console.log(components);  // { red: 'ff', green: 'cc', blue: '99' }

コード003

function getColorComponents(color: number, array: boolean, string: boolean): any {
	let red : number | string = color >> 16;
	let green: number | string = color >> 8 & 0xFF;
	let blue: number | string = color & 0xFF;
	if (string) {
		red = red.toString(16);
		green = green.toString(16);
		blue = blue.toString(16);
	}
	if (array) {
		return [red, green, blue];
	} else {
		return {red: red, green: green, blue: blue};
	}
}

04 オブジェクトを型づけする

関数の戻り値も、anyを改めて、きちんと型づけしましょう。オブジェクトは型をObjectにしたのでは、クラスに定義済みでないプロパティが加えられません。そこで、以下のコード004は、関数の戻り値の型づけにオブジェクト型リテラル(「TypeScript入門 04: オブジェクト型リテラルとインタフェースを使う」02「型定義をつくる」参照)を使いました。なお、配列要素にUnion型を用いるときは、要素の型を丸かっこ()でくくります。

コード004

function getColorComponents(color: number, array: boolean, string: boolean): 
	(number | string)[] |
	{red: number | string, green: number | string, blue: number | string}
{
	let red : number | string = color >> 16;
	let green: number | string = color >> 8 & 0xFF;
	let blue: number | string = color & 0xFF;
	if (string) {
		red = red.toString(16);
		green = green.toString(16);
		blue = blue.toString(16);
	}
	if (array) {
		return [red, green, blue];
	} else {
		return {red: red, green: green, blue: blue};
	}
}

05 引数を配列でまとめる

関数に渡すブーリアン値の引数は、あとあとオプションの数が増える場合に備えて、まとめてしまいます。以下のコード005は、引数をブーリアン値の配列にしました。これなら、手直しもさほど多くありません。

let components = getColorComponents(0xFFCC99, [false, true]);
console.log(components);

コード005

function getColorComponents(color: number, format: boolean[]): 
	(number | string)[] |
	{red: number | string, green: number | string, blue: number | string}
{
	let red : number | string = color >> 16;
	let green: number | string = color >> 8 & 0xFF;
	let blue: number | string = color & 0xFF;
	if (format[1]) {
		red = red.toString(16);
		green = green.toString(16);
		blue = blue.toString(16);
	}
	if (format[0]) {
		return [red, green, blue];
	} else {
		return {red: red, green: green, blue: blue};
	}
}

06 複数のフラグを列挙型でまとめる

配列でまとめるとコードは簡単なものの、どの要素が何を決めるのかわかりにくくなります。列挙型enumを使うと、数値が名前で表せます。そして、ビット演算を用いれば、複数のフラグがひとつの整数で表せるのです(「2進数・16進数とビット演算」02「複数のフラグをひとつの整数で表す」)。以下のコード006は、列挙型とビット演算を使って書き替えました。

console.log(getColorComponents(0xFFCC99));  // { red: 255, green: 204, blue: 153 }
console.log(getColorComponents(0xFFCC99, Format.STRING));  // { red: 'ff', green: 'cc', blue: '99' }
console.log(getColorComponents(0xFFCC99, Format.ARRAY | Format.STRING));  // [ 'ff', 'cc', '99' ]

コード006

enum Format {ARRAY = 1, STRING = 2};
console.log(Format);  // { '1': 'ARRAY', '2': 'STRING', ARRAY: 1, STRING: 2 }
function getColorComponents(color: number, format = 0): 
	(number | string)[] |
	{red: number | string, green: number | string, blue: number | string}
{
	let red : number | string = color >> 16;
	let green: number | string = color >> 8 & 0xFF;
	let blue: number | string = color & 0xFF;
	if ((format & 2) === Format.STRING) {
		red = red.toString(16);
		green = green.toString(16);
		blue = blue.toString(16);
	}
	if ((format & 1) === Format.ARRAY) {
		return [red, green, blue];
	} else {
		return {red: red, green: green, blue: blue};
	}
}

07 Union型に名前をつける

前掲コード006では、数値(number )か文字(string )という型づけがあちこちで使われています。型の別名(type alias)を用いると、ひとつの名前でまとめてしまえます。以下のコード007のようにわかりやすい名前にすれば、スクリプトも見やすくなります。なお、配列はジェネリック型で定めました(別の書き方を示しただけですので、とくに大きな違いはありません)。

コード007

enum Format {ARRAY = 1, STRING = 2};
type NumberOrString = number | string;
console.log(Format);  // { '1': 'ARRAY', '2': 'STRING', ARRAY: 1, STRING: 2 }
function getColorComponents(color: number, format = 0): 
	Array<NumberOrString> |
	{red: NumberOrString, green: NumberOrString, blue: NumberOrString}
{
	let red : NumberOrString = color >> 16;
	let green: NumberOrString = color >> 8 & 0xFF;
	let blue: NumberOrString = color & 0xFF;
	if ((format & 2) === Format.STRING) {
		red = red.toString(16);
		green = green.toString(16);
		blue = blue.toString(16);
	}
	if ((format & 1) === Format.ARRAY) {
		return [red, green, blue];
	} else {
		return {red: red, green: green, blue: blue};
	}
}
4
1
0

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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?