検索
ホームページウェブフロントエンドjsチュートリアルAngular のタイプセーフ ルートでランタイム エラーを排除する

Eliminate Runtime Errors with Type-safe Routes in Angular

Angular アプリケーションのリファクタリングは、諸刃の剣になる可能性があります。一方で、コードベースの保守性とスケーラビリティを向上させることができます。一方、意図しない変更から機能を保護するために必要な予防策を講じていない場合、ルートの破損につながる可能性があります。広範なテストを作成したり、ルートにしっかりとした型付けの概念を実装したりすると、このリスクを軽減できますが、これらのアプローチは時間がかかる可能性があり、常に実行可能であるとは限りません。この記事では、手動でのテスト作業やカスタム型の注釈の記述を必要とせずに、コンパイル時に壊れたルートを自動的に検出する、より効率的なソリューションを検討します。ネストされたコンポーネントを含むサンプル Angular アプリケーションを実装し、typesafe-routes ライブラリを使用して開発者のエクスペリエンスを向上させ、パラメーターの解析を容易にすることで、このアプローチを実証します。

コンパイル時に壊れたルートを自動的に検出する利点を説明するために、DashboardComponent (/dashboard)、OrgsComponent (/orgs/:orgId)、および LocationsComponent (/orgs) の 3 つのネストされたコンポーネントを含むサンプル Angular アプリケーションを実装します。 /:orgId/locations/:locationId)。この例を設定するには、次のコード部分に示すように、typesafe-routes ライブラリをインストールし、その createRoutes 関数を使用してルート ツリーを定義する必要があります。

// app.routes.ts
import { createRoutes, int } from "typesafe-routes";

export const r = createRoutes({
  dashboard: {
    path: ["dashboard"], // ~> "/dashboard"
  },
  orgs: {
    path: ["orgs", int("orgId")], // ~> "/orgs/:orgId"
    children: {
      locations: {
        path: ["locations", int("locationId")], // ~> "locations/:locationId"
        query: [int.optional("page")], // ~> "?page=[number]"
      },
    },
  },
});

コードの断片を詳しく見てみましょう。 typesafe-routes から createRoutes をインポートし、最初の引数としてルートを渡します。これらのルートは、ルート レベルでダッシュボードと組織という 2 つのプロパティを持つネストされたオブジェクトとして定義されます。これらの各プロパティにはパスが割り当てられ、配列の形式でセグメントを指定します。たとえば、["dashboard"] 配列はパス /dashboard に対応します。 orgs パスには、整数型の orgId という名前のパラメータが含まれているため、より複雑です。 integer はネイティブ JavaScript 型ではなく、バックグラウンドで数値を使用して整数の特性を模倣する int 関数を使用して定義されたカスタム型であることに注意してください。 orgs ルートには Children プロパティがあり、locations という 1 つの子ルートを指定します。 location ルートは orgs ルートに似ていますが、int 型の追加のオプションの検索パラメータ ページを指定します。

createRoutes は、ルートに関する情報を使用して、Proxy オブジェクトでラップされたコンテキストを作成します。そのプロキシ オブジェクトの詳細を知る必要はありませんが、そのオブジェクトのおかげで、アプリケーション内のどこにでもすべてのルート仕様にアクセスして、ルートとパラメータをレンダリングおよび解析できることを理解することが重要です。

createRoutes によって返された Proxy オブジェクトを r に割り当てました。これは、r.dashboard を使用してダッシュボードのパス、r.orgs.locations を使用してロケーションのパスなどにアクセスできることを意味します。

レンダリングテンプレート

ルートを定義したら、次のステップ、angular-router への登録に進むことができます。

// app.routes.ts
import { createRoutes, int } from "typesafe-routes";

export const r = createRoutes({
  dashboard: {
    path: ["dashboard"], // ~> "/dashboard"
  },
  orgs: {
    path: ["orgs", int("orgId")], // ~> "/orgs/:orgId"
    children: {
      locations: {
        path: ["locations", int("locationId")], // ~> "locations/:locationId"
        query: [int.optional("page")], // ~> "?page=[number]"
      },
    },
  },
});

コードの一部は、以前に定義したルート ツリーをミラーリングする、Angular Router のネストされたルートを含む一般的なセットアップを示しています。ただし、一般的なプレーン文字列を使用してパス テンプレート (orgs/:orgId など) を指定する代わりに、typesafe-routes/angular-router からテンプレート関数をインポートし、それを使用してパス テンプレートを生成します。 DashboardComponent と OrgsComponent の場合は、対応するパス r.dashboard と r.orgs を指定して template を呼び出すだけで、テンプレートを取得できます。ただし、残りのコンポーネント LocationsComponent は OrgsComponent の子であるため相対パスが必要ですが、Angular Router の場合は絶対パス orgs/:orgId/locations/:locationId になるため、r.orgs.locations を使用して生成することはできません。ルート テンプレートをネストする場合は相対パスが必要です。

相対パスを生成するには、_ リンクを使用できます。これにより、アンダースコア文字より前のすべてが実質的に省略されます。この場合、template(r.orgs._.locations) を使用して相対パスを生成できます。これは、絶対パスをレンダリングする必要があるシナリオだけでなく、相対パスを必要とする状況でも同じルート ツリーを再利用できるため、便利な機能です。

この時点で、お気に入りの IDE (Visual Studio Code など) でオートコンプリートとタイプミス防止をすでに利用しています。また、createRoutes を使用すると、すべてのタイプを最初のルート定義まで追跡できるため、将来の変更によってルート パスのスペルミスやタイプミスが警告されます。

レンダリングリンク

ルート テンプレートを指定したので、リンクのレンダリングに進みたいと思います。そのために、型のシリアル化や型チェックなどのリンクをレンダリングするレンダリング関数を利用する単純なコンポーネントを作成したいと考えています。次の例は、アプリケーション内の他のコンポーネントを参照するアンカー要素のリストをレンダリングするコンポーネントを示しています。

// app.routes.ts
import { Routes } from "@angular/router";
import { template } from "typesafe-routes/angular-router";

export const routes: Routes = [
  {
    path: template(r.dashboard), // ~> "dashboard"
    component: DashboardComponent,
  },
  {
    path: template(r.orgs), // ~> "orgs/:orgId"
    component: OrgsComponent,
    children: [
      {
        path: template(r.orgs._.locations), // ~> "locations/:locationId"
        component: LocationsComponent,
      },
    ],
  },
];

コード例では、typesafe-routes/angular-router から render と renderPath をインポートします。 renderPath はパスをレンダリングしますが、render はリンク リストのクエリ パラメータをさらにシリアル化します。また、r というプロキシ オブジェクトをインポートします。これにより、以前に定義されたルートに関する情報にアクセスし、レンダリングする目的のルートを定義できるようになります。

まず、renderPath 関数を使用して、dashboardLink と orgsLink を作成します。最初のパラメータとして、レンダリングされるルートのパスを表す前述のプロキシ オブジェクトを取ります。 2 番目のパラメーターは、app.routes.ts の createRoutes で以前に定義されたパラメーターの名前とタイプに一致するパラメーター値を持つレコードです。戻り値は、対応するコンポーネントに属するパスを含む文字列です。

3 番目の例の render 関数はパスと検索パラメータの両方をレンダリングするため、パラメータ定義にパスとクエリ プロパティが必要です。ここでの戻り値は、パスとクエリの 2 つのプロパティを持つオブジェクトです。 2 つのプロパティを [routerLink] 属性と [queryParams] 属性の値として設定します。

パラメータの解析

パラメータの解析は、typesafe-routes の重要な部分です。上記のルート定義中に、いくつかのパラメーターを定義し、それらに整数のような型 int を与えました。ただし、パラメーター値は Location オブジェクトなどのさまざまなソースから取得されるため、文字列ベースになります。便利なことに、typesafe-routes は、これらの文字列を解析して目的の型にキャストするヘルパー関数をエクスポートします。解析は、前に作成したプロキシ オブジェクト r に基づいて行われます。つまり、パラメータがどのルートに属しているかをライブラリに伝える必要があります。次の例では、2 つの一般的な解析シナリオを示してそれを示します。

// app.routes.ts
import { createRoutes, int } from "typesafe-routes";

export const r = createRoutes({
  dashboard: {
    path: ["dashboard"], // ~> "/dashboard"
  },
  orgs: {
    path: ["orgs", int("orgId")], // ~> "/orgs/:orgId"
    children: {
      locations: {
        path: ["locations", int("locationId")], // ~> "locations/:locationId"
        query: [int.optional("page")], // ~> "?page=[number]"
      },
    },
  },
});

location.href orgs/1/location/2?page=5 の場合、Angular では this.route.snapshot.queryParams を使用して文字列ベースのクエリ パラメータにアクセスでき、文字列ベースのパス パラメータはこれを通じて提供されます。ルート.スナップショット.パラメータ。 r.orgs.locations および this.route.snapshot.queryParams で parseQuery を使用すると、ページ パラメーターを数値として持つオブジェクトを取得できます。 r.orgs._.locations および this.route.snapshot.params で parsePath を使用すると、解析された locationId を取得します。この場合、r.orgs._.locations は相対パスであり、_ リンクの前のすべてのセグメントが省略されるため、結果のオブジェクトには orgId が存在しません。

typesafe-routes の解析関数は多用途であり、parse を使用して location.href 文字列からすべてのパラメータを一度に直接抽出することもできます。

// app.routes.ts
import { Routes } from "@angular/router";
import { template } from "typesafe-routes/angular-router";

export const routes: Routes = [
  {
    path: template(r.dashboard), // ~> "dashboard"
    component: DashboardComponent,
  },
  {
    path: template(r.orgs), // ~> "orgs/:orgId"
    component: OrgsComponent,
    children: [
      {
        path: template(r.orgs._.locations), // ~> "locations/:locationId"
        component: LocationsComponent,
      },
    ],
  },
];

パラメータに関する型情報の抽出は、InferQueryParams、InferPathParams、または InferParams を介して可能です。ここでは、InferQueryParams ユーティリティ タイプのデモを示します。

// app.component.ts
import { render, renderPath } from "typesafe-routes/angular-router";
import { r } from "./app.routes";

@Component({
  selector: "app-root",
  imports: [RouterOutlet, RouterLink],
  template: `
    <h1 id="Absolute-Links">Absolute Links</h1>
    
`, }) export class AppComponent { dashboardLink = renderPath(r.dashboard, {}); // ~> dashboard orgsLink = renderPath(r.orgs, { orgId: 123 }); // ~> orgs/123 locationLink = render(r.orgs.locations, { path: { orgId: 321, locationId: 654 }, query: { page: 42 }, }); // ~> { path: "orgs/321/location/654", query: { page: "42" }} } // ...

まとめ

このチュートリアルを締めくくるために、ルートの信頼できる唯一の情報源である単一のルート ツリー r を作成しました。これに基づいて、コンポーネントを Angular Router に登録するために使用するテンプレートをレンダリングしました。動的パス セグメントとクエリ パラメーターを使用してパスをレンダリングしました。パラメータを解析して文字列値から対応する型に変換しました。私たちは、型定義を 1 つも書かずに、すべてをタイプセーフな方法で実行しました。新しい機能の開発中にバグを簡単に防止し、将来のリファクタリングをさらに容易にする、堅牢なルート ツリーを確立しました。

ただし、typesafe-routes には、さまざまな組み込みパラメータ タイプ、カスタム パラメータ タイプの簡単な統合、サブパスの操作、カスタム テンプレート文字列の定義など、さらに多くの機能があります。残念ながら、このチュートリアルですべてを説明することはできませんが、公式ドキュメントにアクセスして詳細を読むことができます。

プロジェクトを支援する

もちろん、このチュートリアルで示した例に実装できる潜在的な改善点も数多くあります。たとえば、r.orgs.locations などのプロキシ オブジェクトに基づいたパス定義を受け取るリンク レンダリング用のカスタム ディレクティブです。もう 1 つの例は、Angular Router の Routes 配列を自動的に生成する関数です。これにより、重複したコードが効果的に排除され、最初のコード ブロックで createRoutes で作成されたルート ツリーとルートの同期を保つ必要がなくなりました。

ただし、これらは多くの貢献方法の中のほんの一部にすぎません。最も一般的な方法は、もちろん、共有したり、バグを報告したり、GitHub リポジトリで PR を開くことです。このライブラリを使用して、開発エクスペリエンスが向上すると思われる場合は、私にコーヒーをおごっていただいても構いません。フィードバックを残したり、質問したりできる Discord チャンネルもあります。

以上がAngular のタイプセーフ ルートでランタイム エラーを排除するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
PythonとJavaScript:それぞれの強みを理解するPythonとJavaScript:それぞれの強みを理解するMay 06, 2025 am 12:15 AM

PythonとJavaScriptにはそれぞれ独自の利点があり、選択はプロジェクトのニーズと個人的な好みに依存します。 1. Pythonは、データサイエンスやバックエンド開発に適した簡潔な構文を備えた学習が簡単ですが、実行速度が遅くなっています。 2。JavaScriptはフロントエンド開発のいたるところにあり、強力な非同期プログラミング機能を備えています。 node.jsはフルスタックの開発に適していますが、構文は複雑でエラーが発生しやすい場合があります。

JavaScriptのコア:CまたはCの上に構築されていますか?JavaScriptのコア:CまたはCの上に構築されていますか?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc;それは、解釈されていることを解釈しました。

JavaScriptアプリケーション:フロントエンドからバックエンドまでJavaScriptアプリケーション:フロントエンドからバックエンドまでMay 04, 2025 am 12:12 AM

JavaScriptは、フロントエンドおよびバックエンド開発に使用できます。フロントエンドは、DOM操作を介してユーザーエクスペリエンスを強化し、バックエンドはnode.jsを介してサーバータスクを処理することを処理します。 1.フロントエンドの例:Webページテキストのコンテンツを変更します。 2。バックエンドの例:node.jsサーバーを作成します。

Python vs. Javascript:どの言語を学ぶべきですか?Python vs. Javascript:どの言語を学ぶべきですか?May 03, 2025 am 12:10 AM

PythonまたはJavaScriptの選択は、キャリア開発、学習曲線、エコシステムに基づいている必要があります。1)キャリア開発:Pythonはデータサイエンスとバックエンド開発に適していますが、JavaScriptはフロントエンドおよびフルスタック開発に適しています。 2)学習曲線:Python構文は簡潔で初心者に適しています。 JavaScriptの構文は柔軟です。 3)エコシステム:Pythonには豊富な科学コンピューティングライブラリがあり、JavaScriptには強力なフロントエンドフレームワークがあります。

JavaScriptフレームワーク:最新のWeb開発のパワーJavaScriptフレームワーク:最新のWeb開発のパワーMay 02, 2025 am 12:04 AM

JavaScriptフレームワークのパワーは、開発を簡素化し、ユーザーエクスペリエンスとアプリケーションのパフォーマンスを向上させることにあります。フレームワークを選択するときは、次のことを検討してください。1。プロジェクトのサイズと複雑さ、2。チームエクスペリエンス、3。エコシステムとコミュニティサポート。

JavaScript、C、およびブラウザの関係JavaScript、C、およびブラウザの関係May 01, 2025 am 12:06 AM

はじめに私はあなたがそれを奇妙に思うかもしれないことを知っています、JavaScript、C、およびブラウザは正確に何をしなければなりませんか?彼らは無関係であるように見えますが、実際、彼らは現代のウェブ開発において非常に重要な役割を果たしています。今日は、これら3つの間の密接なつながりについて説明します。この記事を通して、JavaScriptがブラウザでどのように実行されるか、ブラウザエンジンでのCの役割、およびそれらが協力してWebページのレンダリングと相互作用を駆動する方法を学びます。私たちは皆、JavaScriptとブラウザの関係を知っています。 JavaScriptは、フロントエンド開発のコア言語です。ブラウザで直接実行され、Webページが鮮明で興味深いものになります。なぜJavascrを疑問に思ったことがありますか

node.jsは、型を使用してストリーミングしますnode.jsは、型を使用してストリーミングしますApr 30, 2025 am 08:22 AM

node.jsは、主にストリームのおかげで、効率的なI/Oで優れています。 ストリームはデータを段階的に処理し、メモリの過負荷を回避します。大きなファイル、ネットワークタスク、リアルタイムアプリケーションの場合。ストリームとTypeScriptのタイプの安全性を組み合わせることで、パワーが作成されます

Python vs. JavaScript:パフォーマンスと効率の考慮事項Python vs. JavaScript:パフォーマンスと効率の考慮事項Apr 30, 2025 am 12:08 AM

PythonとJavaScriptのパフォーマンスと効率の違いは、主に以下に反映されています。1)解釈された言語として、Pythonはゆっくりと実行されますが、開発効率が高く、迅速なプロトタイプ開発に適しています。 2)JavaScriptはブラウザ内の単一のスレッドに限定されていますが、マルチスレッドおよび非同期I/Oを使用してnode.jsのパフォーマンスを改善でき、両方とも実際のプロジェクトで利点があります。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

PhpStorm Mac バージョン

PhpStorm Mac バージョン

最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、