【TypeScript】基本型のまとめ
この記事の内容
TypeScriptは体系的に学んだことなかったので、
改めて公式ドキュメントを読んでいくことにしました。
その1回目として、Basic Typesの章を読んだので、そのまとめをまとめておこうと思います。
TypeScript: Handbook - Basic Types
Boolean / Number / String
JavaScriptと同じ。
真偽値、数値、文字列(順不同)。
Array
配列を表す型。
書き方は2通りある。
let list1: number[] = [1, 2, 3]; // 1. 型名[] let list2: Array<number> = [1, 2, 3]; // Array<型名>
Tuple
Arrayのそれぞれの要素に対して、型指定して宣言ができる型。
let x: [string, number]; x = ["hello", 10];// OK x = [10, "hello"];// Error
要素には、配列と同じようにアクセスできる。
console.log(x[0].substring(0)); // "hello"
Enum
数値をひとまとまりにして、名前付けして型宣言ができる。いわゆるEnum。
値を指定しなければ0からインクリメントされた値となる。
指定すれば、そこからインクリメントされた値となる。
※以下の例参照
enum Color { Red = 1, Green, Blue = 18, Pink, } console.log(Color.Red)// 1 console.log(Color.Green)// 2 console.log(Color.Blue)// 18 console.log(Color.Pink)// 19
index指定してアクセスすることで、名前を取得できる。
console.log(Color[1])// Red console.log(Color[2])// Green console.log(Color[18])// Blue console.log(Color[19])// Pink
Unknown (v3.0 ~)
未定の型としてunknownで定義できる。
ユーザーの入力値によって、動的に型が変わりうる場合などに使用する。
let notSure: unknown = 4; notSure = "maybe a string instead"; // OK notSure = false;
また型ガードetcによって型が定まるまで利用できない。
declare const maybe: unknown; const aNumber: number = maybe; // Error: Type 'unknown' is not assignable to type 'number' if (maybe === true) { const aBoolean: boolean = maybe;// OK, 型ガードによってmaybeはbooleanになっている const aString: string = maybe;// Error, booleanなので、string型の変数には代入できない } if (typeof maybe === "string") { const aString: string = maybe;//OK, 型ガードによってmaybeはstringになっている const aBoolean: boolean = maybe;// Error, stringなので、boolean型の変数には代入できない }
Any
3rdパーティライブラリ使うときなどに、型チェックで苦戦することがある。
そういう時の回避策としてany型を使用できる。
any型を指定すると、コンパイル時の型チェックの対象から外れるためコンパイルエラーを回避できる。
しかし、コンパイル時の型チェックこそTypeScriptの恩恵が得られる部分なので、any型は極力使わないようにするべき。
let looselyTyped: any = 4; looselyTyped.ifItExsists();// OK looselyTYped.toFixed();// OK
また、any型はネストされた下位のプロパティにも伝播する。
let looselyTyped: any = {}; let d = looselyTyped.a.b.c.d; // aもbもcもdもany型になる
Void
any型がすべての型を含むのとは反対に、型を持たないことを表すのがvoid型。
戻り値を持たない関数の、戻り値の型として使用するのが一般的で、変数の型として使用することはあまりない。
※その場合、null("strictNullChecks"が無効の場合のみ)かundefinedしか割り当てられないため。
function warnUser(): void { console.log("This is my warging message"); } let unusable: void = undefined; unusable = null; // OK, ただし '--strictNullChecks' ではない場合
Null / Undefined
undefined値とnull値に対応する型としてそれぞれundefined型、null型が使用できる。
void型と同じく、単体で使用する用途はない。
後述するように union typeによる使用が一般的。
// これらの値しか割り当てできない let u: undefined = undefined; let n: null = null;
undefined値とnull値は他のすべてのタイプのサブタイプとなる。
つまり、numberの変数に対し、undefined値やnull値を割り当てられる。
ただ、"—strictNullChecks"指定をしている場合は、null値はunknown型、undefined値はunknown型とvoid型にしか割り当てができなくなる。
例えば、stringかnullかundefinedが入る変数を定義したいときは、以下のようにunion typeを使って、型定義できる。
let nullableString: string | null | undefined = null;
Never
neverは何もないことを表す型。例えば、必ずエラーを投げる関数の戻り値として使用する。
変数は型ガードによって絶対に真とならないように狭められた場合にneverになる。
neverはすべての型のサブタイプとなり、すべての型に割り当てることができる
一方で、どの型もneverのサブタイプとならないので、neverに割り当てることはできない。
(never自身は除く)
any もneverに割り当てることはできない。
let a: string = "hoge"; let func1 = (): never => { throw new Error(); }; a = func1();// neverをstringに代入 ※実行時はerror let an: any = {}; let n1: never = an;// これは不可 let n2: never = func1();// never自身はOK
Object
object型はプリミティブでない型を表す。つまり、number, string, boolean, symbol, null, undefined以外の型である。
object型を使うと、Object.create()のようなAPIをより適切に表せる。
declare function create(o: object | null): void; //以下はOK create({ prop: 0}); create(null); //以下はNG create(51); create("string"); create(false); create(undefined);
Type Assertions (型ガード)
開発者の方がTypescriptより値の型を知ってるケースがあり、そういう場合にType assertionsを使うことで、型をコンパイラに伝えれる。
ほかの言語でいうところのキャスト。
方法は2通りある。
- asによる型ガード
let someValue: any = "this is a string"; let strLength: number = (someValue as string).length;
- <>による型ガード
let someValue: any = "this is a string"; let strLength: number = (<string>someValue).length;
どちらを使うかは好みによるが、TSXではasによるものしか使用できない。
まとめ / 感想
改めて学習すると、知らなかった仕様を色々知ることができました。
(strictNullChecksの有無による違いなど)
引き続き、次の章も進めていきたいと思います。