タタッと!ドラゴンさん🐉

タタッ!と書いてく記事まとめ

【React Hooks】Hooksどれ使うの問題① [拡張記事]

Powered By qiita.com

問題1

以下は、非同期処理の状態管理を行うコードです。非同期処理をしたあとの結果でステート更新ができるフックを使用しています。

const initialPosts: Post[] = [];

const [posts, getPosts, isPending] = ■■■■■■■■■■■■(
  async (currentPosts: Post[], payload: void) => {
    const response = await fetch('https://api.example.com/posts');
    const newPosts: Post[] = await response.json();
    
    return newPosts;
  },
  initialPosts
);

const handleClick = () => {
  getPosts();
};

return (
  <div>
    <button onClick={handleClick} disabled={isPending}>
      {isPending ? '読み込み中...' : '投稿を取得'}
    </button>
    <ul>
      {posts.map(post => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  </div>
);

問1の答えと解説を見る

正解: useActionState

解説: useActionStateは、非同期処理とステート管理を組み合わせたフックで、useTransition + useReducerのような機能を提供します。非同期処理の実行中はisPendingフラグでローディング状態を管理でき、処理完了後に自動的にステートが更新されます。第一引数には非同期処理を行う関数、第二引数には初期値を指定します。このフックにより、複雑な非同期ステート管理を簡潔に記述できます。

問題2

useEffectでデータ取得を行う際に発生する、親コンポーネントのデータフェッチが完了するまで子コンポーネントのデータフェッチが開始されず、全体の表示速度が遅くなる問題を■■■■■■■■■■■問題と呼びます。

問2の答えと解説を見る

正解: ウォーターフォール

解説: ウォーターフォール問題は、コンポーネントが階層的にデータを取得する際、親から子へと順次データフェッチが行われる現象です。本来並列で実行できるAPI呼び出しが順次実行されるため、全体的なパフォーマンスが低下します。この問題を回避するには、React QueryやSWR、TanStack Queryなどのデータフェッチライブラリを使用するか、データ取得を上位コンポーネントでまとめて行うアプローチが有効です。

問題3

以下は、DOM要素への直接アクセスを行うコードです。適切なフック名を埋めてください。

const MyComponent = () => {
  const inputRef = ■■■■■■■■(null);
  
  const focusInput = () => {
    inputRef.current?.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>フォーカスを当てる</button>
    </div>
  );
};

問3の答えと解説を見る

正解: useRef

解説: useRefは、DOM要素への参照や再レンダリングを引き起こさない値の保持に使用されるフックです。DOM要素にアクセスする場合、refオブジェクトのcurrentプロパティを通じて実際のDOM要素を取得できます。TypeScriptでは、null許容型で初期化し、アクセス時には?演算子やnull チェックを行うことで型安全性を保ちます。useStateと異なり、値の変更時に再レンダリングが発生しないため、パフォーマンス上のメリットもあります。

問題4

以下は、楽観的更新を実装するコードです。適切なフック名を埋めてください。

function LikeButton() {
  const [likes, setLikes] = useState(0);

  const [optimisticLikes, addOptimisticLike] = ■■■■■■■■■■■■(
    likes,
    (state: number) => state + 1
  );

  const handleClick = async () => {
    addOptimisticLike();

    try {
      await fetch('/api/like', { method: 'POST' });
      setLikes(likes + 1);
    } catch (error) {
      // エラー時は楽観的な更新が自動的にロールバックされる
    }
  };

  return (
    <button onClick={handleClick}>
      いいね!({optimisticLikes})
    </button>
  );
}

問4の答えと解説を見る

正解: useOptimistic

解説: useOptimisticは、楽観的更新(Optimistic UI)を実装するためのフックです。ユーザーのアクション結果を即座に画面に反映し、バックグラウンドで実際の処理を行うことでUXを向上させます。第一引数には実際のステート、第二引数には楽観的更新時の変換関数を指定します。API呼び出しが失敗した場合、楽観的な更新は自動的にロールバックされ、元の状態に戻ります。いいね機能やフォーム送信などでよく使用されるパターンです。

問題5

以下のコードで、検索クエリの更新を遅延させるために使用すべきフック名を埋めてください。

import React, { useState } from 'react';
import ExpensiveList from './ExpensiveList';

function SearchableList() {
  const [searchQuery, setSearchQuery] = useState('');
  const ■■■■■■■■■■■■ = ■■■■■■■■■■■■(searchQuery);

  const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchQuery(e.target.value);
  };

  return (
    <div>
      <input 
        type="text" 
        value={searchQuery}
        onChange={handleSearch} 
        placeholder="検索..."
      />
      <ExpensiveList searchText={■■■■■■■■■■■■} />
    </div>
  );
}

問5の答えと解説を見る

正解: deferredQuery, useDeferredValue, deferredQuery

解説: useDeferredValueは、値の更新を遅延させることができるフックです。useTransitionが関数自体を遅延するのに対し、useDeferredValueは値を遅延させます。主な用途は、サードパーティコンポーネントなど、コードを直接制御できない場合です。入力値は即座に更新されますが、コストの高いコンポーネントには遅延された値が渡されるため、入力のレスポンシブ性を維持しながらパフォーマンスを向上させることができます。

問題6

以下は、複数の関連する状態を管理するコードです。適切なフック名を埋めてください。

interface FormState {
  name: string;
  email: string;
  isValid: boolean;
}

type FormAction = 
  | { type: 'SET_NAME'; payload: string }
  | { type: 'SET_EMAIL'; payload: string }
  | { type: 'VALIDATE' };

function formReducer(state: FormState, action: FormAction): FormState {
  switch (action.type) {
    case 'SET_NAME':
      return { ...state, name: action.payload };
    case 'SET_EMAIL':
      return { ...state, email: action.payload };
    case 'VALIDATE':
      return { ...state, isValid: state.name !== '' && state.email !== '' };
    default:
      return state;
  }
}

function Form() {
  const [formState, dispatch] = ■■■■■■■■■■■■(formReducer, {
    name: '',
    email: '',
    isValid: false
  });
  
  return (
    <form>
      <input 
        value={formState.name}
        onChange={(e) => dispatch({ type: 'SET_NAME', payload: e.target.value })}
      />
      <input 
        value={formState.email}
        onChange={(e) => dispatch({ type: 'SET_EMAIL', payload: e.target.value })}
      />
    </form>
  );
}

問6の答えと解説を見る

正解: useReducer

解説: useReducerは、複数の関連する状態や複雑な状態更新ロジックを扱う際に有効なフックです。useStateと比較して、アクション(action)という概念を使って状態の変更を一元管理できます。TypeScriptでは、StateとActionの型を適切に定義することで、型安全な状態管理が可能になります。複数の状態が密接に関連している場合や、条件分岐が多い更新ロジックがある場合にuseReducerを選択することで、コードの保守性と可読性が向上します。

問題7

以下は、優先度の低い状態更新を後回しにするコードです。適切なフック名を埋めてください。

function Search() {
  const [searchTerm, setSearchTerm] = useState('');
  const [results, setResults] = useState<SearchResult[]>([]);
  const [isPending, ■■■■■■■■■■■■] = ■■■■■■■■■■■■();

  const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchTerm(e.target.value);

    ■■■■■■■■■■■■(() => {
      // 大量のデータを検索する処理(時間がかかる)
      const filtered = performExpensiveSearch(e.target.value);
      setResults(filtered);
    });
  };

  return (
    <>
      <input value={searchTerm} onChange={handleSearch} />
      {isPending && <div>更新中...</div>}
      <SearchResults results={results} />
    </>
  );
}

問7の答えと解説を見る

正解: startTransition, useTransition, startTransition

解説: useTransitionは、優先度の低い状態更新を後回しにできるフックです。ユーザーの入力などの高優先度の更新を妨げることなく、重い処理を実行できます。isPendingフラグを使用して処理中の状態を表示し、startTransition関数で優先度の低い更新をラップします。検索機能、ページネーション、タブ切り替えなど、即座の反応が不要な処理に適用することで、ユーザー体験を大幅に向上させることができます。React 18の concurrent features の一部として導入されました。

問題8

useEffectでデータ取得を行う際に発生する、複数のリクエストが同時に発生した場合に古いリクエストの結果が新しいリクエストの結果を上書きしてしまう問題を■■■■■■■■■■■■■問題と呼びます。

問8の答えと解説を見る

正解: レースコンディション

解説: レースコンディション問題は、非同期処理において複数のリクエストが競合状態になる問題です。例えば検索機能で「りんご」を検索後すぐに「りんごジュース」を検索した場合、「りんご」のAPI応答が遅くて後から到着すると、新しい検索結果を古い結果で上書きしてしまいます。この問題を避けるには、useEffectのクリーンアップ関数でAbortControllerを使用するか、React QueryやSWRなどのライブラリを使用することが推奨されます。これらのライブラリは自動的にリクエストの競合を管理してくれます。

問題9

以下は、一意のIDを生成するコードです。アクセシビリティSSRの安全性のために使用されるフック名を埋めてください。

function Form() {
  const id = ■■■■■■■();

  return (
    <form>
      <div>
        <label htmlFor={`${id}-name`}>名前:</label>
        <input id={`${id}-name`} type="text" />
      </div>
      <div>
        <label htmlFor={`${id}-email`}>メール:</label>
        <input id={`${id}-email`} type="email" />
      </div>
    </form>
  );
}

問9の答えと解説を見る

正解: useId

解説: useIdは、一意のIDを生成するためのフックです。主にアクセシビリティの向上(ラベルとフォーム要素の紐付け)とSSR(サーバーサイドレンダリング)の安全性のために使用されます。ランダムなIDを使用するとサーバーとクライアントで異なるIDが生成され、ハイドレーション時に不整合が発生する可能性がありますが、useIdは一貫したIDを生成するため、この問題を回避できます。複数のID が必要な場合は、基本IDに接尾辞を付けて使用します。

問題10

以下は、DOMの変更を同期的に処理するコードです。useEffectではちらつきが発生してしまうため、適切なフック名を埋めてください。

function NoFlickerComponent() {
  const [position, setPosition] = useState({ x: 0, y: 0 });

  ■■■■■■■■■■■■(() => {
    setPosition({ 
      x: window.innerWidth - 100, 
      y: window.innerHeight - 100 
    });
  }, []);

  return (
    <div
      style={{
        position: 'absolute',
        left: `${position.x}px`,
        top: `${position.y}px`
      }}
    >
      Hello World
    </div>
  );
}

問10の答えと解説を見る

正解: useLayoutEffect

解説: useLayoutEffectは、DOMの変更を同期的に処理するためのフックです。useEffectと異なり、ブラウザが画面を描画する前に実行されるため、視覚的なちらつき(flicker)を防ぐことができます。DOM要素のサイズや位置を測定・変更する処理、スクロール位置の調整、初期レンダリング時のレイアウト計算などに使用されます。ただし、同期実行のためパフォーマンスに影響を与える可能性があるので、必要な場合のみ使用し、通常はuseEffectを優先すべきです。

まとめ

これらのReact Hooksは、モダンなReactアプリケーション開発において重要な役割を果たします。特に以下の点に注意して実装することが重要です:

  • パフォーマンス: useMemo、useCallback、useTransition を適切に使用してレンダリング最適化を図る
  • データ取得: useEffectでの直接的なデータ取得は避け、専用ライブラリの使用を検討する
  • 型安全性: TypeScriptの型システムを活用し、各フックに適切な型定義を行う
  • ユーザー体験: useOptimistic、useTransitionを使用して応答性の高いUIを実現する

各種プロトコルにおける暗号化方式と鍵の利用法について:公開鍵で暗号化するんだっけ?秘密鍵で暗号化するんだっけ?

本記事では、代表的なネットワークプロトコルにおける暗号化処理と、公開鍵・秘密鍵の使い分けに関する要点を技術的に整理する。 クッソ間違うので目安とか無いかと思って調べてみた。


1. 鍵の基本的な役割

暗号化方式において、公開鍵暗号共通鍵暗号が存在する。

目的に応じて以下のように使い分ける。

目的 使用する鍵 代表例
内容の秘匿 受信者の公開鍵 PGP, TLS(鍵交換時)
送信者の証明 送信者の秘密鍵 電子署名, PGP署名, S/MIME

2. 各種プロトコルにおける鍵の利用法一覧

プロトコル 鍵の使い方 用途 鍵の種類 説明
TLS/SSLHTTPS サーバの公開鍵で共通鍵を暗号化 暗号化 公開鍵 → 共通鍵 公開鍵で共通鍵を安全に送信後、共通鍵暗号で通信
SSH クライアントまたはサーバの秘密鍵で署名・認証 署名+暗号化 公開鍵・秘密鍵 サーバまたはクライアント認証で鍵を利用
PGP/GPG 相手の公開鍵で暗号化、自分の秘密鍵で署名 暗号化+署名 公開鍵・秘密鍵 公開鍵で秘匿、秘密鍵で署名を実施
S/MIME 受信者の公開鍵で暗号化、送信者の秘密鍵で署名 暗号化+署名 公開鍵・秘密鍵 電子メールの暗号化と署名に使用
IPSec 事前共有鍵またはDH鍵交換で共通鍵を確立 暗号化 共通鍵 共通鍵を用いた対称暗号方式
Wi-Fi(WPA2等) PSK等から共通鍵を生成 暗号化 共通鍵 公開鍵暗号は基本使用せず共通鍵暗号を採用
X.509証明書 認証局秘密鍵で証明書に署名 署名 秘密鍵 発行元の信頼性を担保するための署名処理

3. まとめ

  • 暗号化を通じた秘匿性の確保には、受信者の公開鍵を使用する。
  • メッセージの真正性・送信者証明には、送信者の秘密鍵で署名する。
  • 通信の高速性と効率を重視するプロトコルTLSIPSecなど)は、共通鍵暗号とのハイブリッド方式を採用している。

プロトコルごとに目的と使用される鍵の種類を把握すると試験対策に役立ちそうですなぁ

【TypeScript】boolean | undefined で詰まったこと

TypeScriptの型システムは、コードの信頼性を高めるために非常に重要な役割を果たしています。特に、null および undefined の扱いは厳格に管理されており、これが型安全性を支える基盤となっています。

今回詰まったのはこちら

const value : boolean | undefined = getValue();
const isTrue : boolean = value // 型ERROR

valueがundefinedの可能性があっても、undefinedはfalsyなのだから実質的にtrue / falseのbool値じゃないの???

なぜなのか調べてみた結果⬇️


boolean | undefinedboolean 型の変数に直接代入できない理由

TypeScriptにおいて、boolean | undefined 型の値を直接 boolean 型に代入しようとするとコンパイルエラーになります。これは、次の2点によるものです:

  • Strict Null Checks(厳格なnullチェック)
    --strictNullChecks オプションが有効だと、undefinednull は他の型とは別の独立した型になります。
    boolean 型は true または false のみを許容するため、undefined を含む値は代入できません。

  • 型の部分集合関係
    boolean | undefinedboolean のスーパーセット(より広い型)なので、逆方向の代入は安全でないと判断されます。

コード例と対策

let maybeFlag: boolean | undefined = undefined;
let flag: boolean;

// エラー:Type 'boolean | undefined' is not assignable to type 'boolean'
// flag = maybeFlag;

// 対策1: undefined チェック
if (maybeFlag !== undefined) {
  flag = maybeFlag;
} else {
  flag = false;
}

// 対策2: Null合体演算子 (??)
flag = maybeFlag ?? false;

プロンプトはJSON形式が良いとのこと

プロンプトはJSON形式がいいらしい

{
  "meta_prompt": {
    "description": "このメタプロンプトは、AIが最適なプロンプトを生成するための指示を定義します。出力はJSON形式で、明確な構造と詳細な指示を含む必要があります。",
    "instructions": [
      "生成するプロンプトは、ユーザーの目的に合わせた明確な指示を提供すること。",
      "プロンプト内には、背景情報、目的、出力形式、制約条件、評価基準を含めること。",
      "出力は全てJSON形式で提供し、各フィールドは意味を持つキーで表現すること。",
      "各フィールドの説明やサンプルを可能な限り具体的に記述すること。"
    ],
    "fields": {
      "title": "プロンプトのタイトルまたは目的",
      "background": "タスクに関する背景情報や前提条件",
      "objectives": "プロンプトを使用する目的および期待されるアウトカム",
      "steps": "タスクを完了するための具体的な手順(例:1. 情報収集 2. 分析 3. 出力)",
      "output_format": "出力する情報の形式(例:JSON、箇条書き、段落など)",
      "constraints": "守るべき制約事項(例:文字数制限、特定の用語の使用禁止など)",
      "evaluation": "生成結果の評価基準や成功の指標"
    },
    "example": {
      "title": "未来都市の詳細な描写",
      "background": "未来の技術と建築が融合した都市のイメージを描く",
      "objectives": "読者に未来都市の具体的なイメージと魅力を伝える",
      "steps": [
        "都市の全体像を説明する",
        "主要な建造物とその機能を詳細に記述する",
        "未来技術の具体例を挙げる"
      ],
      "output_format": "段落形式と箇条書きを組み合わせた文章",
      "constraints": "専門用語は簡単な説明を加える",
      "evaluation": "詳細さ、創造性、分かりやすさ"
    },
    "notes": "このメタプロンプトは、AIがユーザーの意図に沿った効果的なプロンプトを構築できるように設計されています。必要に応じて各フィールドを拡張・修正してください。"
  }
}

ブックマークレットを使って強いエンジニア

GitHub 検索で動的な日付を使うブックマークレット

GitHub の検索クエリは、デフォルトでは静的な日付を使う必要があります。しかし、JavaScript を用いたブックマークレットを使えば、毎回現在の日付から一週間前の日付を自動計算してクエリに反映させることが可能になります。

ブックマークレットの仕組み

このブックマークレットは、以下の処理を実行します。

  1. 今日の日付を取得
    ブラウザの Date オブジェクトを利用して現在の日付を取得します。

  2. 一週間前の日付を計算
    現在の日付から 7 日分のミリ秒を引くことで、一週間前の日付を求めます。

  3. 日付をフォーマット
    一週間前の日付を YYYY-MM-DD 形式に整形します。

  4. GitHub の検索クエリを生成
    is:pr is:merged merged:>2025-03-25」という形式のクエリ文字列を作成します。

  5. リダイレクト
    生成したクエリを用いて、GitHub の検索結果ページにリダイレクトします。

ブックマークレットのコード

以下のコードをコピーして、ブックマークレットとして登録してください。

javascript:(function(){
  var today = new Date();
  var oneWeekAgo = new Date(today.getTime() - 7*24*60*60*1000);
  var yyyy = oneWeekAgo.getFullYear();
  var mm = ('0' + (oneWeekAgo.getMonth()+1)).slice(-2);
  var dd = ('0' + oneWeekAgo.getDate()).slice(-2);
  var dateString = yyyy + '-' + mm + '-' + dd;
  var query = "is:pr is:merged merged:>" + dateString;
  window.location.href = "https://github.com/search?q=" + encodeURIComponent(query) + "&type=Issues";
})();

ブックマークレットの作成手順

  1. コードをコピー
    上記のコードをすべてコピーします。

  2. 新規ブックマークを作成
    ブラウザで新しいブックマークを作成し、名前を「GitHub PR Last Week」など分かりやすいものに設定します。

  3. URL 部分にコードを貼り付け
    作成したブックマークの URL(またはアドレス)欄に、先ほどコピーしたコードを貼り付けます。

  4. 利用方法
    GitHub で動的に1週間以内にマージされた PR を検索したいときは、このブックマークをクリックするだけです。すると、自動で現在の日付から一週間前の日付が計算され、検索結果が表示されます。

ユーザースクリプトでの実装

ChromeFirefox の場合、Tampermonkey などのユーザースクリプトマネージャを利用することで、さらに柔軟な自動化が可能です。例えば、GitHub の特定のページにアクセスした際に自動でクエリを更新するなどのカスタマイズができます。


以上の方法を使えば、GitHub の検索クエリに動的な日付を組み込むことができ、常に最新の結果を取得することが可能になります。

XXX : ユーザー名 YYY : リポジトリ

javascript:(function(){
  var today = new Date();
  var oneWeekAgo = new Date(today.getTime() - 7*24*60*60*1000);
  var yyyy = oneWeekAgo.getFullYear();
  var mm = ('0' + (oneWeekAgo.getMonth()+1)).slice(-2);
  var dd = ('0' + oneWeekAgo.getDate()).slice(-2);
  var dateString = yyyy + '-' + mm + '-' + dd;
  var query = "repo:XXX/YYY is:pr is:merged merged:>" + dateString;
  window.location.href = "https://github.com/search?q=" + encodeURIComponent(query) + "&type=Issues";
})();

iframeとsandbox

iframeとは iframeは「インラインフレーム」(inline frame)の略で、HTMLの要素の一つです。Webページ内に別のWebページを埋め込むために使用されます。

<iframe src="https://example.com" width="500" height="300"></iframe>

iframeの主な特徴 別ドメインのコンテンツ埋め込み: 自分のWebサイト内に他のWebサイトのコンテンツを表示できます 独立した環境: iframe内のコンテンツは基本的に親ページとは分離された環境で動作します セキュリティ上の懸念: 適切な保護がないと、セキュリティリスクになる可能性があります 一般的な用途 YouTubeなどの動画埋め込み Googleマップの埋め込み 広告の表示 外部サービスのフォーム(決済システムなど) レガシーシステムの一部を新しいサイトに統合 セキュリティリスク iframeはセキュリティ上のリスクがあります: クリックジャッキング: 悪意あるサイトが透明なiframeを使って、ユーザーに意図しないアクションを実行させる クロスサイトスクリプティング(XSS): iframe内のコンテンツが親ページにアクセスする 情報漏洩: 適切な保護がないと、iframe内のコンテンツが親ページの情報にアクセスできる sandbox属性 これらのリスクを軽減するために、HTML5ではsandbox属性が導入されました:

<iframe src="https://example.com" sandbox="allow-scripts allow-same-origin"></iframe>

sandbox属性は、iframe内のコンテンツに対して様々な制限を課します: JavaScriptの実行を制限 フォーム送信を禁止 ポップアップを禁止 など 必要な機能だけを許可することで、セキュリティリスクを最小限に抑えることができます。

<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=XXXXXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>

Google Tag Managerとは Google Tag Managerは、Webサイトやアプリにマーケティングタグ(コード)を追加・管理するためのGoogleのツールです。主な機能: タグ管理: Google AnalyticsFacebookピクセルなど様々なマーケティングタグを一元管理 非エンジニアでも操作可能: コードを変更せずにタグの追加・変更が可能 条件付き実行: 特定のページや条件でのみタグを実行できる セキュリティ問題と対策 指摘されている問題は、このiframeにsandbox属性が設定されていないことです。このiframeはJavaScriptが無効な環境でGTMを動作させるためのフォールバックとして機能します。 対策 以下のようにsandbox属性を追加することをお勧めします:

<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=XXX-XXXXXX"
height="0" width="0" style="display:none;visibility:hidden" 
sandbox="allow-scripts allow-same-origin"></iframe></noscript>

sandbox="allow-scripts allow-same-origin"を追加することで、必要最小限の権限(スクリプト実行と同一オリジンポリシーの維持)を許可しつつ、その他の潜在的に危険な操作を制限できます。 Google Tag Managerは信頼できるサービスですが、セキュリティのベストプラクティスとしてsandbox属性を追加した方がよいです。

【memo】TypeScript 5.8 要約

TypeScript 5.8 新機能

こちら確認してください

devblogs.microsoft.com

Granular Checks for Branches in Return Expressions

TypeScript 5.8では、型システムがreturn文内の条件式を特別に扱い、各分岐が関数の戻り値型と互換性があるかを検証することで、型エラーを検出できるようになりました。

declare const untypedCache: Map<any, any>;

function getUrlObject(urlString: string): URL {
    return untypedCache.has(urlString) ?
        untypedCache.get(urlString) :
        urlString; // エラー: string型はURL型に割り当てられません
}

Support for require() of ECMAScript Modules in --module nodenext

--module nodenextフラグが有効な場合、CommonJSモジュールからESMモジュールへのrequire()呼び出しでエラーを回避する機能が追加されました。

// CommonJS (file.cjs)
const esmModule = require('./esm-module.mjs');
esmModule.someFunction();

--module node18

Node.js 18ユーザー向けの安定した--module node18フラグが導入されました。--module nodenextの特定の動作を含みません。

tsc --module node18 file.ts

The --erasableSyntaxOnly Option

--erasableSyntaxOnlyフラグが導入され、ランタイム動作を持つTypeScript固有の構文に対してエラーを出すことができるようになりました。これは、Node.jsでTypeScriptファイルを直接実行する際の互換性チェックに役立ちます。

class C {
    constructor(public x: number) { } // エラー: erasableSyntaxOnlyが有効な場合、この構文は許可されません
}

The --libReplacement Flag

デフォルトのlibファイルの置換を無効にする--libReplacementフラグが導入されました。

tsc --libReplacement false file.ts

Preserved Computed Property Names in Declaration Files

TypeScript 5.8では、クラスの計算プロパティ名でエンティティ名を保持するようになり、宣言ファイルの予測可能性が向上しました。

export let propName = "theAnswer";

export class MyClass {
    [propName] = 42;
}

Optimizations on Program Loads and Updates

プログラムのロードと更新時間を改善するための最適化が導入されました。パス正規化の配列割り当てを回避し、プロジェクト構造が変わらない編集ではオプションの再検証を回避するなどの改善が含まれます。

Restrictions on Import Assertions Under --module nodenext

--module nodenextが有効な場合、import assertions(assert構文)を使用するとエラーが発生するようになりました。import attributes(with構文)を代わりに使用する必要があります。

import data from "./data.json" assert { type: "json" }; // エラー: import assertionsはimport attributesに置き換えられました。'with'を使用してください。