# Object Properties

{% tabs %}
{% tab title="📗 參考" %}

* TypeScript ⟩&#x20;
  * [Optional Properties](https://www.typescriptlang.org/docs/handbook/2/objects.html#optional-properties)
  * [Index Signatures](https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures)
    {% endtab %}

{% tab title="Second Tab" %}

{% endtab %}
{% endtabs %}

## Optional

{% hint style="warning" %}
當宣告 **x?: T** 時，x 的型別實際上是 **T | undefined**
{% endhint %}

```typescript
// 
interface PaintOptions {
  x?: number;              // ⭐️ optional
  y?: number;
}

/*
interface Shape {
  paint(opts: PaintOptions = {});
}
*/

const shape = getShape();

shape.paint({ });
shape.paint({ x: 100 });
shape.paint({ y: 100 });
shape.paint({ x: 100, y: 100 });
```

## readonly

{% hint style="info" %}
**readonly** 與 **const** 的作用差不多，會保護 [Primitives](/web/appendix/typescript/type/primitives.md) 不受更改，但對於 [Object](/web/appendix/typescript/type/object.md) 來說，雖然**不能更改物件本身**，但**可更改**其**屬性**。
{% endhint %}

```typescript
interface SomeType {
  readonly prop: string;      // ⭐️ readonly
}
```

{% hint style="danger" %}
**readonly** properties **can be modified** via **aliasing**❗️
{% endhint %}

```typescript
interface Person {
  name: string;
  age : number;
}
 
interface ReadOnlyPerson {
  readonly name: string;      // ⭐️ readonly
  readonly age : number;      // ⭐️ readonly
}

// writable
let person: Person = {
  name: "Person McPersonface",
  age: 42,
};
 
// ⭐️ point to same person
let readonlyPerson: ReadOnlyPerson = person;
 
readonlyPerson.age;              // prints '42'
person.age++;                    // person is writable ⭐️
readonlyPerson.age;              // prints '43'
```

## Index Signatures

{% hint style="info" %}
TypeScript 的 [index signature](https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures) 類似於 Swift 的 [subscript](https://docs.swift.org/swift-book/LanguageGuide/Subscripts.html)。
{% endhint %}

```typescript
interface StringArray {
//╭─── ⭐️ ───╮
  [ index: T ]: string;       // ⭐️ index signature
}                             //    T = string or number
 
const a: StringArray = getStringArray();
const item = a[0];
```

{% hint style="warning" %}
An **index signature** property **type T** must be either ‘**string**’ or ‘**number**’.
{% endhint %}

{% hint style="danger" %}
It is possible to support both types of indexers, but the **type returned** from a **numeric indexer** must be a **subtype** of the **type returned** from the **string indexer**. This is because when **indexing** with a **number**, JavaScript will actually **convert** that to a **string** before indexing into an object. That means:

* **a\[100] === a\["100"]**
  {% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lochiwei.gitbook.io/web/appendix/typescript/type/object/properties.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
