オブジェクトとは何か?
下記の記事で紹介したプリミティブ型という基本的な7つの型以外のものを、
オブジェクトといいます。
-
参考【TypeScript基礎】プリミティブ型、基本的な型の種類について
TypeScriptの特徴は何と言っても、型にありますが、そんな型の中でも、中心的な役割を占める、プリミティブ型について、詳しく解説します。 文字ではなく、動画で観たい方は、下記をご参考ください。 h ...
続きを見る
具体的には、string、number
bigint、boolean、undefined
symbol、null以外の型のことですね。
他の言語だと、オブジェクト = クラスなどに結び付けられがちですが、
TypeScriptの場合、クラスだけにとどまらない、広い範囲を含むのが特徴です。
これは、JavaScriptやTypeScriptの大きな特徴かなと思いまして、
最初はまあまあ戸惑うかなとおもいます。
代表的なものとしては、
const val = {
obj1: 123,
obj2: 'hello'
}
console.log(val.obj1) // 123と表示される
こんな感じのコードがあげられます。
定義方法としては、
{}の中に、プロパティ名(キー):値と定義します。
オブジェクトの中身(プロパティ)を得ている、
console.log(val.obj1)の部分は、
プロパティアクセスに当たります。
ちなみにプロパティアクセスの方法としては、
console.log(val["obj1"]) // 123と表示される
のような記法もあります。
いくつかのデータをまとめて管理したいときなどに、
オブジェクトが利用されることが多いです。
なお、省略記法もあり、
例えば次のようにかけます。
//省略しない書き方
const hello = 'Hello World'
const user1 = {
hello: hello,
age: 28,
}
console.log(user1.hello)
//省略記法
const hello = 'Hello World'
const user1 = {
hello,
age: 28,
}
console.log(user1.hello)
変数名とプロパティ名が同じ場合、
: 変数名の部分を省略できます。
ただ、上記のような省略記法については、
何だかんだでそんなに遭遇したことがないので、
どこまで浸透しているのかは微妙なところです。
可読性という観点では、
正直どちらがいいとは断定しづらいですね。
オブジェクトの型
オブジェクトの型は、
例えば次のように記述します。
const val: {
obj1: number,
obj2: string
} = {
obj1: 123,
obj2: 'hello'
}
console.log(val.obj1) // 123と表示される
「うん?どれが型だ?
うじゃうじゃしているな」って思った方もいるかもしれません。
この場合、変数valの型は、
{ obj1: number, obj2: string }型となります。
複数の値に対してそれぞれ型を定義しているだけで、
一つ一つについては、プリミティブのときと同様ではあります。
すなわち、上記のvalオブジェクトは、
obj1がnumberで、obj2がstringの構造をもつ、
オブジェクトだということで、
上記のような型になっています。
ただ、記述が長くなるので、
type文を使うことが実際には多いです。
type文とは、自分で
カスタムの型を宣言する文法記法のようなものです。
type valobj = {
obj1: number,
obj2: string
}
const val: valobj = {
obj1: 123,
obj2: 'hello'
}
console.log(val.obj1)
type文で宣言した型は、
上記のように型注釈に記載できます。
これだとvalの定義自体は簡潔になった感じがしますよね。
type文は、上記のように、
型を宣言する構文です
すでに存在する型に対して、
別名をつけることができます。
よくある使い方としては、
typeの宣言を別のtypesディレクトリのようなものに切り出して、
まとめて宣言して、各ファイルでそれぞれの型を呼び出すようにすると、
見通しが良くなるかなと思います。
型引数(ジェネリクス)
上記のtype文と関連して、
型引数という、type文の中でだけ有効な型として
扱えるものがあります。
type valobj<T> = {
obj1: number,
obj2: T
}
このような型引数を持つ型は、
ジェネリック型といいます。
上記の型を実際に使う場合は、
引数に型を指定します。
const val: valobj<string> = {
obj1: 123,
obj2: 'hello'
}
この場合、
stringが引数に渡されているので、
valobj型のTはstringとなり、
{ obj1: number, obj2: string }型と同様になります。
このあたりは、関数の引数と
似ていますね。
なお型引数を指定した場合、
呼び出し側で引数を指定しないと、
コンパイルエラーになります。
//型引数なしでは呼び出せない。
const val: valobj = {
obj1: 123,
obj2: 'hello'
}
そのため、省略可能なオプショナルな型引数にする場合は、
予めデフォルト値を定義しておく必要があります。
type valobj<T = string> = {
obj1: number,
obj2: T
}
const val: valobj = {
obj1: 123,
obj2: 'hello'
}
この場合、型引数が指定されないと、
Tはstring型になります。
配列
配列は、[]で定義される、
複数のデータをまとめたデータ構造で、
オブジェクトの一種です。
配列については、他のプログラミング言語でも
嫌というほど見ていると思うので、
イメージしやすいかと思います。
平たく言えば、複数のデータが入っている箱のような感じですね。
TypeScriptだと、下記のように配列定義します。
const arr = ['hello', 'alice', 123]
console.log(arr)
arrという変数に['hello', 'alice', 123]というものが代入されていますね。
これは、'hello'、'alice'、123の3つの値が、
arrという配列の変数に格納されている感じです。
通常の変数であれば、
一対一に対応していましたが、
オブジェクトのように、一対複数のように定義できるのが、
配列の特徴です。
配列の値にアクセスするには、
arr[0]
と番号を指定します。
0始まりからなので、先頭の要素は、
arr[0]というふうに取得します。
arr[0]だと、上記の場合、
'hello'の文字列が取得できます。
ちなみに、プログラミング言語によっては、
0ではなく、1スタートだったりすることもありますが、
基本的には0スタートの言語が多いです。
TypeScriptにおける配列は、上記の番号、
0とか1といったプロパティ名を持つ、
オブジェクトともいえるので、
実は、配列はオブジェクトの一種でもあります。
オブジェクトのプロパティアクセスの方法で
値を取得することができますもんね。
プログラミング言語によっては、
上記のオブジェクトのようなデータ構造と、
配列は全く別のものだったりするので、
これもTypeScript、JavaScriptの大きな特徴ですね。
配列の型
さて、TypeScriptの特徴は型ですが、
配列の型は、
const arr: string[] = ['hello', 'alice']
というふうに、型名[]と記述します。
上記の場合、stringの要素を持つ配列とわかりますね。
もう一つの記法として、
const arr: Array<string> = ['hello', 'alice']
というのも存在します。
こちらは組み込みのジェネリック型にあたります。
(すなわち、stringというものを型引数として渡している感じですね)
どちらの記法が良いというわけではありませんが、
最初の方が、スッキリ書けるので、
私は前者の記法のほうが好きです。
ジェネリクスっぽく書きたい場合は、
後者にすると良いと思います。
また、最初に定義したような、
複数の型が混ざった配列の場合は、
ユニオン型というものを使って、
const arr: (string | number)[] = ['hello', 'alice', 123]
というふうに記述することもできます。
ユニオン型とは、上記の | の部分ですね。
stringまたはnumberという感じです。
https://typescriptbook.jp/reference/values-types-variables/union