# Kiểu NonNullable\<T> được sử dụng để loại bỏ các kiểu null và undefined khỏi kiểu T (ok)

### Áp dụng một ví dụ rất hay sử dụng

<figure><img src="https://2086325979-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOfwU52oyTCInVkN26DVZ%2Fuploads%2FJQWRfcg7w3cvi6D2fWks%2Fimage.png?alt=media&#x26;token=c0001bca-275c-4692-b93c-eb1c05add490" alt=""><figcaption></figcaption></figure>

```javascript

export type GetPublishedPagesListQuery =  {
  __typename ?: 'RootQuery',
  pages: {
    __typename ?: 'RootQueryToPageConnection',
      edges: Array <{
        __typename?: 'RootQueryToPageConnectionEdge',
        node: {
          __typename?: 'Page',
          title: string | null,
          slug: string | null
        }
      }>
  } | null
};
```

```typescript
import { GetPublishedPagesListQuery } from "./graphql";
export type IPageListItem = NonNullable<GetPublishedPagesListQuery['pages']>['edges'][number]['node'];
```

```typescript
export const GET_PUBLISHED_PAGES_LIST = gql`
  query GetPublishedPagesList {
    pages(where: { status: PUBLISH }) {
      edges {
        node {
          title
          slug
        }
      }
    }
  }
`;

```

```typescript
query GetPublishedPagesList {
  pages(where: { status: PUBLISH }) {
    edges {
      node {
        title
        slug
      }
    }
  }
}
```

```typescript
{
  "data": {
    "pages": {
      "edges": [
        {
          "node": {
            "title": "My account",
            "slug": "my-account"
          }
        },
        {
          "node": {
            "title": "Checkout",
            "slug": "checkout"
          }
        },
        {
          "node": {
            "title": "Cart",
            "slug": "cart"
          }
        },
        {
          "node": {
            "title": "Shop",
            "slug": "shop"
          }
        },
        {
          "node": {
            "title": "Sample Page",
            "slug": "sample-page"
          }
        },
        {
          "node": {
            "title": "How to use the test data",
            "slug": "how-to"
          }
        }
      ]
    }
  }
}
```

Trong TypeScript, kiểu `NonNullable<T>` được sử dụng để loại bỏ các kiểu `null` và `undefined` khỏi kiểu `T`. Đoạn mã bạn cung cấp:

TypeScript

```
type NonNullable<T> = T & {};
```

thực hiện điều này bằng cách sử dụng phép giao nhau kiểu (`&`).

**Giải thích:**

1. **`T & {}`**:
   * `T` đại diện cho kiểu đầu vào.
   * `{}` đại diện cho một kiểu đối tượng rỗng.
   * Phép giao nhau kiểu (`&`) tạo ra một kiểu mới là giao điểm của `T` và `{}`.
2. **Loại bỏ `null` và `undefined`**:
   * Khi bạn thực hiện phép giao nhau với `{}`, TypeScript loại bỏ `null` và `undefined` khỏi kết quả. Điều này xảy ra bởi vì `null` và `undefined` không thể được gán cho một kiểu đối tượng (`{}`).
   * Ví dụ, nếu `T` có thể là `string | null | undefined`, thì `T & {}` sẽ trở thành `string`.

**Ví dụ sử dụng:**

TypeScript

```typescript
type MaybeString = string | null | undefined;

type DefinitelyString = NonNullable<MaybeString>; // DefinitelyString là string

let maybeValue: MaybeString = "hello";
let definitelyValue: DefinitelyString;

maybeValue = "world";
definitelyValue = maybeValue; // OK

//maybeValue = null;
//definitelyValue = maybeValue; // Error: Type 'null' is not assignable to type 'string'.

//maybeValue = undefined;
//definitelyValue = maybeValue; // Error: Type 'undefined' is not assignable to type 'string'.

function processValue(value: NonNullable<string | null | undefined>) {
  console.log(value.toUpperCase());
}

processValue("test"); // OK
//processValue(null); //Error
//processValue(undefined); //Error

```

**Tại sao lại sử dụng `{}`?**

* `{}` đại diện cho kiểu đối tượng cơ bản nhất, cho phép tất cả các giá trị đối tượng.
* Bằng cách giao `T` với `{}`, bạn đang nói rằng kết quả phải là một kiểu có thể gán cho một đối tượng, loại bỏ các giá trị không thể gán cho đối tượng như `null` và `undefined`.

**Lưu ý:**

* TypeScript cung cấp kiểu dựng sẵn `NonNullable<T>` trong các phiên bản gần đây. Vì vậy, bạn thường không cần phải tự định nghĩa nó.
* Tuy nhiên, việc hiểu cách nó hoạt động thông qua phép giao nhau kiểu là hữu ích để nắm bắt các khái niệm kiểu nâng cao của TypeScript.
