LoginSignup
1
1

More than 3 years have passed since last update.

【翻訳】TypeScript Basic Types + α

Posted at

TypeScriptの型について

TypeScript Basic Types

こちらのドキュメントをGoogle翻訳よりもわかりやすく翻訳してみました。
本家にはない説明も加えてありますのでよく読み、用法・用量お守りください。

基本的な型

はじめに

使いやすいプログラムの為に、私たちは「数値」「文字列」「構造」「ブール値」などのもっとも単純なデータ単位を操作できる必要があります。
TypeScriptでは、JavaScriptで期待されるものとほぼ同じ型をサポートしています。
便利な列挙型を利用して、操作を手助けします。

以下、サンプルコードが記述されていますが、TypeScriptの型指定ではJavaScriptとは違い基本的に小文字で始まることに注意してください。
大文字で始まる型宣言は、JavaScriptコードで適切に使用されることはほとんどない非プリミティブのオブジェクトとして参照されてしまうので使用しないでください。

Boolean

最も基本的なデータ型は、単純なtrue/false値で、JavaScriptおよびTypeScriptでbooleanを使用します。

let isDone: boolean = false;

Number

JavaScriptと同様に、TypeScriptの数値はすべて浮動小数点数です。これらの浮動小数点数はnumberを使用します。
16進数(hexadecimal)と10進数(decimal)に加えて、TypeScriptではECMAScript 2015で導入された2進数(binary)と8進数(octal)もサポートしています。

let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;

Bigint

bigint型は、ECMAScriptの新しい規格として定義されています。(upcoming proposal)
number型が扱える正確な数値として52bit(2^53-1bit)ですが、それ以上の値を扱う際に使用する型です。
number型では最大値を超えると表示上 Number.MAX_SAFE_INTEGER = 9007199254740991 になりますが、
bigint型を使用するとJavaScriptで扱える最大値 Number.MAX_VALUE = 1.7976931348623157e+308まで表示することができます。しかし、正確性は保障されないことに変わりはありません。

bigint型は、型安全保障(type guard)も他の型と同様に利用できます。

number型とbigint型は互換性がありません。
2つの型を使って演算を実行するには、型変換(cast)をすることで実行可能になります。参考: mrsekutの備忘録

let foo: bigint = BigInt(100);         // BitInt関数により初期化
let bar: bigint = 100n;                // BitIntリテラルによる割り当て
let integer: number = 10;              // numberリテラルによる割り当て

console.log(foo + bar);                // OK
console.log(foo + integer);            // Error, Type 'bigint' is not assignable to type 'number'.
console.log(foo + BigInt(integer));    // OK

if (typeof foo === "bigint") {         // タイプガードも利用可能
    console.log("'foo' is a bigint.");
} else {
    console.log("'foo' is a floating-point number.");
}

String

Webページやサーバー用のJavaScriptでプログラムを作成する時に、booleannumberに加えてもう一つの型はテキストデータです。
他の言語と同様に、テキストデータを参照するためにstringを使用します。
また、JavaScriptと同様に、TypeScriptも "二重引用符(double quotes)" または '一重引用符(single quotes)' を使用して文字列データを囲みます。
JavaScriptとTypeScriptではCやC#、Javaとは違いchar型が存在しないため、一重引用符を使用することができます。

let color: string = "blue";
color = 'red';

テンプレート文字列も使用することができ、複数行にまたがり式を埋め込むことができます。
これらの文字列は `backtick/backquote` で囲まれ、埋め込み式は ${ expr } です。
複数行にまたがって代入するときは、コード内のインデントも反映されてしまうので注意してください。

let fullName: string = `Bob Bobbington`;
let age: number = 37;
let sentence: string = `Hello, my name is ${ fullName }.

I'll be ${ age + 1 } years old next month.`;

上記の変数sentenceは、次のような宣言と同等です。

let sentence: string =
  "Hello, my name is " + fullName + ".\n\n" +
  "I'll be " + (age + 1) + " years old next month.";

Array

TypeScriptではJavaScriptと同様に値の配列操作ができます。

配列型は2つの方法のいずれかで記述できます。最初の方法では、要素の型に続いて[]を使用してその要素型の配列を宣言します。

let list: number[] = [1, 2, 3];

2つ目は、ジェネリクスであるArray<elemType>を使用する方法です。

let list: Array<number> = [1, 2, 3];

どちらの方法であってもJavaScriptにトランスパイルすると同じ配列になります。

Symbol

symbolは、ECMAScript 2015から導入されたnumberstringのようなプリミティブなデータタイプです。
symbolの値は、Symbolのコンストラクタによって生成されます。

let sym1 = Symbol();
let sym2 = Symbol("key"); // stringキーのオプション

Symbolは、不変(immutable)であり、一意(unique)です。

let sym2 = Symbol("key");
let sym3 = Symbol("key");

sym2 === sym3 // Symbolは一意のため、結果はfalseです

string型のようにSymbolはオブジェクトプロパティのユニークキーとして使用できます。

const sym = Symbol();
let obj = {
    [sym]: "value"
};

console.log(obj[sym]);  // "value"

Symbolは、オブジェクトプロパティとクラスメンバーのような算出プロパティの宣言としても使用できます。

const getClassNameSymbol = Symbol();

class C {
    [getClassNameSymbol](){
       return "C";
    }
}

let c = new C();
let className = c[getClassNameSymbol](); // "C"

以下、Symbolが持つ拡張機能です。詳細はハンドブックをご覧ください。

  • Symbol.hasInstance
  • Symbol.isConcatSpreadable
  • Symbol.iterator
  • Symbol.match
  • Symbol.replace
  • Symbol.search
  • Symbol.species
  • Symbol.split
  • Symbol.toPrimitive
  • Symbol.toStringTag
  • Symbol.unscopables

Tuple

タプル型を使用すると、型はわかっているが同じである必要のない固定数の要素で配列を表現できます。
例えば、文字列と数値のペアとして値を表すことができます。

// タプル型の宣言
let x: [string, number];
// 正しい初期化
x = ["hello", 10]; // OK
// 正しくない初期化
x = [10, "hello"]; // Error

要素が存在するインデックスで要素を取得すると、正しい型が取得できます。

console.log(x[0].substring(1)); // OK
console.log(x[1].substring(1)); // Error, number は substring を持っていません

要素が存在しないインデックスで要素を取得しようとすると、エラーが発生します。

let x: [string, number];
x = ["hello", 10];

x[3] = "world"; // Error, プロパティ '3' は 型 '[string, number]' に存在しません
console.log(x[5].toString()); // Error, プロパティ '4' は 型 '[string, number]' に存在しません

Enum

JavaScriptでは存在していない列挙型ですが、TypeScriptでは列挙型としてenumがあります。
C# のような言語と同様にenumは、数値のセットによってわかりやすい名前を付ける方法です。
ちなみにJavaScriptでも、連想配列(辞書型)として列挙型のように振舞うことは可能です。

enum Color {
  Red,
  Green,
  Blue
}
let c: Color = Color.Green;

デフォルトでは、列挙型は 0 から採番を始めます。手動で採番をするにはメンバーのいずれかに値を与えると変更することが可能です。
下記の例では、 0 ではなく 1 から採番しています。

enum Color {
  Red = 1,
  Green,
  Blue
}
let c: Color = Color.Green;

また、全て手動で設定することも可能です。

enum Color {
  Red = 1,
  Green = 2,
  Blue = 4
}
let c: Color = Color.Green;

列挙型の便利なところは、その値から列挙型した名前を取得できるところです。
例えば、下記の例では値が 2 であるのにもかかわらず、Colorという列挙型で何にマップされているかわからない場合、対応する名前を検索できます。

enum Color {
  Red = 1,
  Green,
  Blue
}
let colorName: string = Color[2];

console.log(colorName); // value値 2 に対応する 'Green' が表示されます

例では数値をvalueとして設定していますが、文字列も設定することが可能です。
その場合、自動採番はされないので全ての列挙に対して値を設定してください。

enum Color {
  Red = "red",
  Green = "green",
  Blue = "blue"
}
let c: Color = Color.Green;

Any

プログラマはアプリケーションの作成時に、型が不明な変数を宣言する場合があります。動的なコンテンツやユーザーまたはサードパーティライブラリ、Native JavaScriptから型が不明な値が返ってくることがあるからです。
プログラマはそれらの不明な型変数をオプトアウトして、コンパイルを通す必要があります。
その時は、any型で宣言します。

let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // 問題なく、booleanを代入できます。

any型は既存のJavaScriptを操作する協力な方法であり、コンパイル中にタイプチェックを徐々にオプトイン/アウトできます。

let notSure: any = 4;
notSure.ifItExists(); // OK, 実行時には ifItExists はおそらく存在している
notSure.toFixed(); // OK, toFixed は存在している (コンパイラはチェックしない)

let prettySure: Object = 4;
prettySure.toFixed(); // Error, 'Object'型に 'toFixed' は存在しません

Objectは非プリミティブ型です。そのため、使用は推奨していません。Do's and Don'ts

any型は、使用する型の一部を知っている場合にも便利ですが、それがすべてではありません。
例えば、any型の配列は様々な型が混在する場合があります。

let list: any[] = [1, true, "free"];

list[1] = 100;

Unknown

unknown型は、型安全なany型です。全ての変数宣言でunknown型を使うことができますが、
unknown型はそれ自体と型注釈、制御フローベースの型絞り込み機能を持ちません。
つまり、実際に使用する際には型を明確に指定する必要があります。

TypeScript 3.0 unknown - サンプルコードと解説

Null and Undefined

TypeScriptでは、undefinednullの両方が明示的な型としてそれぞれ存在しています。
void型のように単独ではあまり役に立ちません。

// これらの型指定された変数に対して他の値を割り当てることはできません
let u: undefined = undefined;
let n: null = null;

デフォルトでは、nullundefinedは他の全ての型の派生型です。
つまりnumberのようなものにnullundefinedを割り当てることができます。

しかし、--strictNullChecksオプションを使うとnullundefinedは、any型にのみ割り当てが可能です。(例外としてundefinedvoid型に割り当て可能です。)

これにより、たくさんの一般的なエラーの助けになります。
一つの変数に対してstring, null, undefinedをそれぞれ割り当てたい時は、string | null | undefinedの様な複合型(ユニオン型)を使うことができます。

--strictNullChecksオプションは使用することを推奨していますが、このハンドブックではオフにしています。

Never

never型は何も発生しない型として表現されます。
使用例として、常に例外をスローする関数式やアロー関数式、または決してreturnされないアロー式の戻り値型などがあります。
また、変数は決して真にならない場合、型推論ではnever型を推論します。

never型は、全ての型の派生型なので、全ての変数に指定できます。
さらに、型無し(no type)はnever型の派生型であり、never型を割り当て可能です。(never型自身を除いて)
ただし、any型にnever型を割り当てることはできません。

never型を返す関数のサンプルをいくつか紹介します。

// この関数は途中でthrowされているため、完了することはありません
function error(message: string): never {
    throw new Error(message);
}

// 上記のerror関数の戻り値がnever型なので、戻り値の型推論結果はnever型です
function fail() {
    return error("Something failed");
}

// この関数は無限ループにより、完了することはありません
function infiniteLoop(): never {
    while (true) {
    }
}

Object

object型は非プリミティブな型を表します。
objectとは違い、number, string, boolean, bigint, symbol, null, undefined はプリミティブです。
object型を使うと、Object.createのようなAPIを適切に表現することができます。

declare function create(o: object | null): void;

create({ prop: 0 }); // OK
create(null); // OK

create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error

型注釈

TypeScriptプログラマは、TypeScriptコンパイラよりもその変数の型について把握している状況があります。
エンティティについて現在の型よりも正確で具体的な型を理解しているときに起こります。

型注釈は、コンパイラに "trust me, I know what I’m doing." (信じて、私は把握しているよ!)と伝える方法です。
TypeScriptでは、他言語のキャストにあるような、型チェックや変数の再構築はしません。
型注釈は実行に影響はありません。コンパイル時に影響する機能です。TypeScriptは、プログラマが型チェックをしている前提で動作します。

型注釈を設定する方法は2種類あります。
"<>"(angle-bracket)記法と as 記法です。

let someValue: any = "this is a string";

let angleBracket: number = (<string>someValue).length;  // <>記法
let asBracket: number = (someValue as string).length;   // as記法

2つのサンプルは同等です。どちらを使用するかは好みです。

ただし、JSXでTypeScriptを使用する場合は as 記法のみ許可されます。

letに関するメモ

既にお気づきかと思いますが、ここまでのサンプルではJavaScriptのvarの代わりにletを使用してきました。
letはES2015でJavaScriptに導入され、varよりも安全であるため、現在では標準とみなされています。
JavaScriptの多くの問題はletを使用して軽減されるため、可能な限りvarの代わりにletを使用する必要があります。
(詳しくは、「let var scope」で検索してみてください。)

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