【TypeScript】宣言と型
変数宣言
TypeScript では、JavaScript 同様letとconstを用いて変数宣言を行います。
その際に変数の型を指定します。
const n: number = 0
const s: string = 'abcde'
const b: boolean = true別の型の値を代入するとエラーになります。
let n: number = 0
n = '1' //Type '"1"' is not assignable to type 'number'.実際のところ、変数宣言の際に必ず型を指定しなければいけないというわけではありません。 初期値に設定したリテラル(値)によって、型推論をしてくれます。
let n = 0 //number
let s = 'abcde' //string
let b = true //boolean関数宣言
TypeScript では、変数同様に関数の引数と戻り値の型を指定します。
function myFunc(n: number, s: string): string {
return 'abcde'
}
const r: string = myFunc(0, 'abcde')引数や戻り値に設定した値の型が異なる場合は、エラーとなります。
引数の型を省略した場合はanyという型になります。
戻り値の型を省略した場合は、returnのリテラルによって決まります。
returnがない場合はvoidとなります。
関数式は以下のように宣言できます。
const myFunc: (n: number, s: string) => string = (n: number, s: string) => {
return 'abcde;
}
const r: string = myFunc(0, 'abcde')型宣言の部分は省略できるのですが、(引数) => 戻り値の型と指定することは覚えておきましょう。
基本の型
string
JavaScript のStringと同様に文字列を表す型です。
const str1: string = 'abcde'
const str2: string = '12345'
const str3: string = `${str1}fghij`number
JavaScript のNumberと同様に数値を表す型です。
整数だけでなく、浮動小数点数や進数もnumberに含まれます。
const num1: number = 10
const num2: number = 10.102
const num3: number = 0xfff文字列の数値は代入することができません。
const num: number = '10' //NGboolean
JavaScript のBooleanと同様に真偽値を表す型です。
取り得る値はtrueまたはfalseです。
const bool1: boolean = true
const bool2: boolean = falsearray
JavaScript のArrayと同様に配列を表す型です。
型宣言には[]またはジェネリクス(<>)を使用します。
const ary1: number[] = [1, 2, 3]
const ary2: Array<number> = [1, 2, 3]object
JavaScript のObjectと同様にオブジェクトを表す型です。
const obj: object = {
field1: 'val1',
field2: 'val2',
}objectの他に、{}を使用することでプロパティとその型を宣言することができます。
ここで宣言していないプロパティへの参照はエラーとなります。
const obj: { id: number; name: string } = {
id: 0001,
name: 'Taro',
}
obj.name = 'Jiro' //OK
obj.age = 20 //プロパティの宣言にないためNGtuple
tupleは[]を使ってデータ構造を表します。
const tuple: [string, number, boolean] = ['abcde', 1, true]上記の例だと、長さ 3 のstring、number、booleanのデータが順に格納された配列、といったイメージになります。
tupleへのアクセスは、配列同様インデックスを使用します。
tuple[0] //'abcde'
tuple[1] //1
tuple[2] //trueundefeind / null
TypeScript では、undefinedとnullに対しても明確に型を指定する必要があります。
const ng: string = undefined //NG
const ok: undefined = undefined //OKconst ng: string = null //NG
const ok: null = null //OK上記は、TypeScript の設定値であるstrictNullChecksがtrueの場合の説明です。
falseに設定すると、ほとんどの型はundefinedやnullを指定しなくても代入ができるようになります。
しかし、多くの場合はエラーの回避のためにtrueを使用します。
void
voidは関数やメソッドの戻り値がないことを表すための型です。
通常、変数に設定することはありません。
function doProcess(): void {
//...
}never
neverはvoidと似ていて、関数やメソッドの戻り値がないことを表すための型です。
voidとの違いは、処理が正常に終了するか否かにあります。
neverは、以下のように処理が最後まで到達することがない場合に使用します。
// 例外スローによって処理が最後まで到達しない
function error(message: string): never {
throw new Error(message)
}// 無限ループによって処理が最後まで到達しない
function infiniteLoop(): never {
while (true) {}
}any
anyはすべての型を表します。
つまり、TypeScript の型チェックを無視して代入をすることができます。
しかし、これは TypeScript の恩恵を無視することになるので、型安全を目指すのであれば多用すべきではありません。
let any1: any = 1
any1 = 'abcde'
any1 = trueunknown
unknownはanyと同じくすべての型を表します。
anyとの違いについて、以下の例をみてください。
const a: any = 1
const u: unknown = 1
a.toUpperCase() //実行時エラー
u.toUpperCase() //コンパイル時エラー数値に対して、大文字に変換するtoUpperCase()を使用しています。
当然これはエラーになるのですが、そのタイミングが異なります。
anyの場合は、実際に実行した時にエラーが発生します。
一方unknownは、コンパイル時にエラーとしてくれます。
要は、型がわかっていないのにプロパティ参照やメソッド実行をするな、と事前に通達してくれます。
ユニオン型
TypeScript では、|を用いることで複数の型を宣言できます。
例えば、以下のようにnumberとstringの 2 つの型を持つ変数を宣言できます。
let ns: number | string = 0
n = '1' //これはエラーにならない現在の値がどの型であるかを調べるために、typeofを使用します。
const x: number | string = 0
console.log(typeof x) //"number"リテラル型
TypeScript の型には、文字や数値などのリテラルを指定することができます。 リテラルを指定すると、変数はそのリテラルのみ代入することができます。
let x: 'A' | 'B' = 'A'
x = 'B' //OK
x = 'C' //NGlet x: 0 | 1 = 0
x = 1 //OK
x = 2 //NG型アサーション
型アサーションとは、不明確な型に対して「これはこの型である」と宣言するためのものです。 そのため型アサーションを行う場合は、プログラマー自身が変数がどの型であるかを把握しておく必要があります。
型アサーションには、asを使用する方法と<>を使用する方法があります。
const x: unknown = 'abcde'
const y: string = (x as string).toUpperCase()
const z: string = (<string>x).toUpperCase()