【超基礎】TypeScriptにおけるオブジェクトについて

# 前提
この記事は、初学者の私が、サバイバルTypeScriptで学んだこと+調べたことをまとめたものになります。

従って、経験則に基づいた発言ではないため、一部慣習とは違っていたり、認知にずれがあったりする可能性がありますので、ぜひコメントで指摘していただけると幸いです。

https://typescriptbook.jp/

# 環境
記事内のコードは以下の環境で動作確認済みです。

- Node.js: v22.10.0
- TypeScript: Version 5.6.3

# オブジェクトとは
- TypeScript(JavaScript)では、プリミティブ型以外のものはすべてオブジェクト
- オブジェクトリテラル`{}`を使う
- プロパティやメソッドを持ち、`.`でアクセス可能
```typescript
const human = { name: "Taro",age: 20 };

console.log(typeof human); //=>object

console.log(human.name); //=>"Taro"
```

# プロパティ、メソッド、フィールド
JSにおいてはプロパティという単語の守備範囲が広く、**プロパティという集合の中にメソッドやフィールドがある**イメージ

また、**JSではメソッドとフィールドの区別自体も曖昧**であるため、メソッドにnullを代入するとフィールドに代わってしまう。

**プロパティ**
　**キーと値の対**。JSではプリミティブ型から関数、オブジェクトまで含む。

**メソッド**
　**オブジェクト中の関数**。オブジェクトに関連付いた動作をする。

**フィールド**
　**オブジェクト中の値を指す**。オブジェクト指向プログラミングの文脈で使われることが多く、プリミティブ型の値を指す。


# オブジェクトと型
### フィールドの型注釈
オブジェクトリテラルの書き方で、プロパティの型注釈が可能

型エイリアスを使い、オブジェクト全体を新しい型として宣言することもできる。
:::note
通常のオブジェクトリテラルでは、プロパティ同士が`,`で区切られるが、型注釈では`;`で区切られる。
:::
```typescript
let human: { name: string; age: number};
human = {name: "Taro", age: number};

type Human: {name: string; age: number};
human: Human = { name: "Taro", age: 20}
```

### メソッドの型注釈
- オブジェクトがメソッドを含む場合は、引数と戻り値について型注釈が可能

➡ 型注釈をしておくことで型の誤りを検知してくれる
```typescript
let calc :{
    doubleNum( n: number ): number;
};

calc = {
    doubleNum( n ){
        return n * 2;
    },
};

console.log(calc.doubleNum(5)); //=>10
```
### object型
`object`型による型注釈もできるが期待しないオブジェクトが代入される可能性や、プロパティに関する情報がないため使用は非推奨

:::note warn
Object型や{}型も存在するが、こちらはプリミティブ型すら許容するためもっと非推奨
:::


# インデックス型
- フィールド名の型のみ指定してプロパティを宣言する
- フィールド名の型は`string` `number` `symbol`のみ
- 後からフィールド名ごと代入できる
```typescript
let obj:{
    [K: string]: number; //Kまたはkeyが慣習
};

obj.a = 5;
```

# 分割代入
- プロパティへのアクセスと代入を一度にできる
- 複数のプロパティを一度に取り出せる
- プロパティ名と代入先の変数名は必然的に同じになる

:::note
メソッドの代入も可能。同名の関数として使用できる。
:::
```typescript
const human{
    name: "taro",
    age: 20
}
const { name, age } = human;

console.log(name) //=>taro
```
### 別名での代入
```typescript
const { name: Namae, age: Nenrei} = human;//別名の変数に代入

console.log(Namae)//=>taro
```
### ネストされたプロパティ
```typescript
//ネストされたオブジェクト
const human = {
    profile: {
        name: "taro",
        age: 20
    },
};

const { profile: {name,age}} = human; 

console.log(name);//=>taro
```

### デフォルト値の指定
分割代入時に、フィールドの値がundefinedの時に代入されるデフォルト値を指定できる
:::note
値がnullの時はデフォルト値でなくnullが代入される
:::
```typescript
const { name = "anonymous", age = 999 }
```

## Shorthand property names
- 分割代入の逆（変数の値をプロパティの値に代入する）
- 逐一アクセスせずに代入できる
```typescript
type Human = { 
    name: string;
    age: number;
};

const name = "taro";
const age = 20;

const human: Human = { name, age };
```
# オプショナルチェーン　`?.`
- nullやundefinedへの誤ったアクセスを防ぐ
- ごり押しでチェックすることもできるが、`?.`により簡単に記述できる
- `?.`でアクセスした値がnullやundefinedだったら、エラー無くundefinedが返されるようになる
- 得られる値の型はundefined型と期待する値の型のユニオン型
```typescript
//プロパティへのアクセス
console.log( human?.sex ) //=> undefined
```
### 関数呼び出し(メソッド呼び出し)
```typescript
console.log(sum?.(1,4))//=> undifined
```

### 配列への参照
```typescript
console.log( numbers?.[0])//=>undefined
```
### デフォルト値の設定
Null合体演算子`??`を使うことで、undefinedが返されたときの動作を設定できる
```typescript
console.log( human?.sex ?? "プロパティがないよ")
```

# オブジェクトのループ
- `for-in`文を使う(古くからある方法)
- プロパティを順に取り出し、[]で指定して取り出す
- `.`でアクセスしようとすると怒られる
### for-in文
```typescript
const human={ name: "taro",  age: 20};

for (const prop in human){
    console.log(prop,human[prop]);
    //name taro
    //age 20
}
```
### for-of文(ES2017以降)
Object.entries　➡　プロパティ名と値
Object.keys　➡　プロパティ名
Object.values　➡　値を取得可能
```typescript
for (const [prop,value] of Object.entries(human)){
    console.log(prop,value)
    //name taro
    //age 20
}
```
# まとめ
以上になります。

慣例から外れた部分があれば指摘していただけると幸いです！！