🦧
TypeScript5.2の新しいキーワード using について

mokun632

mokun632

2023年6月23日
TypeScript

usingとそれにまつわるSymbol.disposeについて

# using

TypeScript5.2 の新しいキーワード using が導入されます。
このキーワードを使用すると、スコープが出た時に Symbol.dispose で指定した関数がリソースの解放する事ができます。

{
  const getResource = () => {
    return {
      [Symbol.dispose]: () => {
        console.log('hoge')
      }
    }
  }
  using resource = getResource();
}

ファイルハンドルやデータベース接続などのリソースを管理する時に役立ちます。

# Symbol.dispose

Symbol.dispose は、JavaScript の新しい Well-known Symbols です。
関数に Symbol.dispose を割り当てる事で、「特定のライフタイムを持つオブジェクト」とみなされます。
using キーワードで使用することができます。

const resource = {
  [Symbol.dispose]: () => {
    console.log("fuga");
  },
};

# await using

Symbol.asyncDispose と await を使って、非同期にリソース解放する事もできます。


const getResource = () => {
  return {
    [Symbol.asyncDispose]: () => {
      console.log('hoge')
    }
  }
}

{
  await using resource = getResource();
}

# Use cases

# ファイルハンドル

import { open } from "node:fs/promises";
const getFileHandle = async (path: string) => {
  const filehandle = await open(path, "r");
  return {
    filehandle,
    [Symbol.asyncDispose]: async () => {
      await filehandle.close();
    },
  };
};
{
  await using file = getFileHandle("thefile.txt");
  // Do stuff with file.filehandle
} // Automatically disposed!

# データベース接続

const getConnection = async () => {
  const connection = await getDb();
  return {
    connection,
    [Symbol.asyncDispose]: async () => {
      await connection.close();
    },
  };
};
{
  await using { connection } = getConnection();
  // Do stuff with connection
} // Automatically closed!

# おまけ

# ネガティブマージンについて

/* divが親要素、pが子要素 */
div {
  width: 400px;
  border: 3px solid black;
}
p {
  margin-left: 10px;
  width: auto;
  margin-right: -50px;
}

この場合、子要素である p タグは、親要素である div タグの右端から 50px 飛び出ます。
この時、p タグの width: auto は margin、border、padding の合計値が親要素の横幅と同じになるよう計算されます。
つまり、p タグの width は、390px になるように計算されます。
ですが、margin-right: -50px;があるので、width: autoは-50px 引かれる分、足されて下記のような計算になります。
10px + 0 + 0 + 440px + 0 + 0 - 50px = 400px

このように見た目上では親要素の横幅である 400px を超えているように見えるのですが、内部的には親要素の横幅と同じになるように計算されています。

# 参考文献

TypeScript 5.2's New Keyword: 'using'