概要TypeScript 2.1 では、型システムに強力な追加機能であるマップ型が導入されました。基本的に、マップされた型を使用すると、属性型をマップすることによって既存の型から新しい型を作成できます。指定したルールに従って、既存の型の各プロパティを変換します。変換された属性によって新しいタイプが形成されます。 マップされた型を使用すると、型システム内の Object.freeze() などのメソッドの効果をキャプチャできます。オブジェクトが凍結されると、そのオブジェクトのプロパティを追加、変更、または削除することはできなくなります。マップされた型を使用せずに、これを型システムでどのようにエンコードできるかを見てみましょう。 インターフェースポイント{ x: 数値; y: 数値; } インターフェース FrozenPoint { 読み取り専用 x: 数値; 読み取り専用 y: 数値; } 関数freezePoint(p: Point): FrozenPoint { Object.freeze(p) を返します。 } const origin = freezePoint({ x: 0, y: 0 }); // エラー! 'x' には代入できません。 // は定数または読み取り専用プロパティです。 原点.x = 42; x と y の 2 つのプロパティを含む Point インターフェイスを定義します。また、すべてのプロパティが readonly を使用して読み取り専用プロパティとして定義されている点を除いて Point と同じである別のインターフェイス FrozenPoint も定義します。 freezePoint 関数は、Point を引数として受け入れてそれをフリーズし、同じオブジェクトを呼び出し元に返します。ただし、オブジェクトの型は FrozenPoint に変更されているため、そのプロパティは読み取り専用として静的に型指定されます。そのため、TypeScript では x プロパティに 42 を割り当てようとするとエラーが発生します。実行時に、割り当ては TypeError をスローするか (厳密モード)、または何もせずに失敗します (非厳密モード)。 上記の例はコンパイルされて正しく動作しますが、2 つの大きな欠点があります。
マップされた型を使用して Object.freeze() を構築するlib.d.ts ファイルで Object.freeze() がどのように定義されているかを見てみましょう。 /** * 既存のプロパティ属性と値の変更を防止し、新しいプロパティの追加を防止します。 * @param o 属性をロックするオブジェクト。 */ フリーズ<T>(o: T): 読み取り専用<T>; このメソッドの戻り値の型は Readonly<T> です。これはマッピング型であり、次のように定義されます。 型 Readonly<T> = { 読み取り専用 [P in keyof T]: T[P] }; この構文は最初は難しいかもしれませんので、ステップごとに分解してみましょう。
Readonly<T> 型はジェネリックなので、T に提供するすべての型は Object.freeze() で正しくラップされます。 const origin = Object.freeze({ x: 0, y: 0 }); // エラー! 'x' には代入できません。 // は定数または読み取り専用プロパティです。 原点.x = 42; マッピングタイプの構文はより直感的である今回は Point 型を例にして、型マッピングの仕組みを大まかに説明します。以下は説明のみを目的としており、TypeScript で使用される解析アルゴリズムを正確に反映するものではないことに注意してください。 型エイリアスから始めます: ReadonlyPoint を Readonly<Point> と入力します。 これで、Readonly<T> のジェネリック型 T を Point 型に置き換えることができます。 タイプ ReadonyPoint = { 読み取り専用 [Point のキーの P]: Point[P] }; T が Point であることがわかったので、keyof Point で表される文字列リテラル型の結合を決定できます。 タイプ ReadonlyPoint = { 読み取り専用 [P in "x" | "y"]: ポイント[p] }; 型 P は各プロパティ x と y を表します。マップされた型の構文を削除して、これらを個別のプロパティとして記述してみましょう。 タイプ ReadonlyPoint = { 読み取り専用x: Point["x"]; 読み取り専用y: Point["y"]; }; 最後に、2 つのルックアップ タイプを解析し、どちらも数値である具体的な x 型と y 型に置き換えることができます。 タイプ ReadonlyPoint = { 読み取り専用 x: 数値; 読み取り専用 y: 数値; }; 最終的に、結果の ReadonlyPoint 型は、手動で作成した FrozenPoint 型と同じになります。 マッピングタイプのその他の例上記の lib.d.ts ファイルでは、組み込みの Readonly<T> 型をすでに確認しました。さらに、TypeScript はさまざまな状況で役立つ他のマップされた型を定義します。次のように: /** * T内のすべてのプロパティをオプションにする */ 型 Partial<T> = { [TのキーのP]?: T[P] }; /** * TからプロパティセットKを選択する */ 型 Pick<T, K は keyof T> を拡張します = { [KのP]: T[P] }; /** * 型TのプロパティKのセットを持つ型を構築する */ 型 Record<K extends string, T> = { [P in K]: T }; 以下にマッピング タイプの例を 2 つ示します。必要に応じて独自のマッピング タイプを記述することもできます。 /** * T内のすべてのプロパティをnull可能にする */ Nullable<T>型 = { [T のキーの P]: T[P] | null }; /** * Tのすべてのプロパティを文字列に変換する */ 型Stringify<T> = { [TのキーのP]: 文字列 }; マップされた型と共用体の組み合わせも興味深いです。 タイプ X = Readonly<Nullable<Stringify<Point>>>; // タイプ X = { // 読み取り専用 x: string | null; // 読み取り専用 y: string | null; // }; マッピングタイプの実際の使用例マッピング型は実際によく見られます。React と Lodash を見てみましょう。
リテラルの型推論の改善以前は、文字列、数値、ブール値のリテラル型 (例: "abc"、1、true) は、明示的な型注釈が存在する場合にのみ推論されていました。 TypeScript 2.1 以降では、リテラル型には常にデフォルト値があると推測されます。 TypeScript 2.0 では、いくつかの新しいリテラル型が追加され、型システムが拡張されました。
型注釈のない const 変数または読み取り専用プロパティの型は、リテラル初期化子の型であると推論されます。型注釈のない初期化された let 変数、var 変数、パラメーター、または非読み取り専用プロパティの型は、初期値の拡張リテラル型であると推論されます。文字列リテラルの拡張型は string 、数値リテラルの拡張型は number 、true または false リテラルの拡張型は boolean 、列挙リテラルの拡張型は enumeration です。 より優れたconst変数推論ローカル変数と var キーワードから始めましょう。 TypeScript は次の変数宣言を見ると、baseUrl 変数が文字列型であると推測します。 var baseUrl = "https://example.com/"; // 推論された型: 文字列 letキーワードで宣言された変数についても同様です。 baseUrl = "https://example.com/" とします。 // 推論された型: 文字列 どちらの変数もいつでも変更される可能性があるため、文字列型であると推測されます。これらはリテラル文字列値で初期化されますが、後で変更することもできます。 ただし、const キーワードを使用して変数を宣言し、文字列リテラルで初期化すると、推論される型は文字列ではなくリテラル型になります。 const baseUrl = "https://example.com/"; // 推論された型: "https://example.com/" 定数文字列変数の値は変わらないため、推論される型はより具体的になります。 baseUrl 変数には、「https://example.com/」以外の値を保持することはできません。 リテラル型推論は他のプリミティブ型にも機能します。定数を直接数値またはブール値で初期化すると、リテラル型が推論されます。 定数 HTTPS_PORT = 443; // 推論された型: 443 定数 rememberMe = true; // 推論された型: true 同様に、初期化子が列挙値の場合、リテラル型が推論されます。 列挙型FlexDirection{ 行、 カラム } const 方向 = FlexDirection.Column; // 推論された型: FlexDirection.Column 方向型は列挙リテラル型である FlexDirection.Column であることに注意してください。 let または var キーワードを使用して方向変数を宣言する場合、その推論された型は FlexDirection である必要があります。 読み取り専用プロパティの推論の改善ローカル const 変数と同様に、リテラル初期化子を持つ読み取り専用プロパティもリテラル型であると推論されます。 クラスApiClient { プライベート読み取り専用 baseUrl = "https://api.example.com/"; // 推論された型: "https://api.example.com/" get(エンドポイント: 文字列) { // ... } } 読み取り専用クラス プロパティは、すぐにまたはコンストラクター内でのみ初期化できます。他の場所で値を変更しようとすると、コンパイル時エラーが発生します。したがって、読み取り専用クラス プロパティの値は変更されないため、そのリテラル型を推測することは合理的です。 もちろん、TypeScript は実行時に何が起こるかわかりません。readonly でマークされたプロパティは、JavaScript コードによっていつでも変更される可能性があります。 readonly 修飾子は、TypeScript コードからのプロパティへのアクセスのみを制限し、実行時には何も行いません。つまり、コンパイル中に削除され、生成された js コードには表示されません。 推論されたリテラル型の有用性const 変数と読み取り専用プロパティのリテラル型を推論することがなぜ便利なのか疑問に思うかもしれません。次のコードを考えてみましょう。 const HTTP_GET = "GET"; // 推論された型: "GET" const HTTP_POST = "POST"; // 推論された型: "POST" 関数 get(url: 文字列、メソッド: "GET" | "POST") { // ... } 取得("https://example.com/", HTTP_GET); HTTP_GET 定数の推論された型が "GET" ではなく文字列だった場合、HTTP_GET を get 関数の 2 番目の引数として渡すことができないため、コンパイル時エラーが発生します。
もちろん、対応する引数が 2 つの特定の文字列値のみを許可する場合、関数の引数として任意の文字列を渡すことはできません。ただし、2 つの定数に対してリテラル型「GET」と「POST」が推論されると、すべて正常に動作します。 以上がTypeScriptのマッピング型とリテラル型推論の改善についての詳しい説明です。TSの詳細については、123WORDPRESS.COMのその他の関連記事もご覧ください。 以下もご興味があるかもしれません:
|
<<: Linux で MySQL スケジュールタスクを実装する方法
>>: Centos7 への mysql8.0rpm のインストール チュートリアル
こんにちは、みんな!技術の話ばかりで髪は切らないトニーです。データベース関数は、何らかの機能を持ち、...
VMware vSphere は、業界をリードする最も信頼性の高い仮想化プラットフォームです。 v...
ページを作成するときに、記述した CSS スタイルが有効にならないことがあります。この現象にはさまざ...
目次DOMContentLoadedとロードjs ブロッキングとは何ですか? CSS ブロッキングと...
この記事では、参考までにMySQL 5.7.18 MSIインストールチュートリアルを紹介します。具体...
1.Docer CEをインストールして使用するこの記事では、CentOS 7 を例に Docker ...
この記事では、VMware Workstation 14 Proのインストールとアクティベーションに...
NginxのGeoモジュールの紹介geo ディレクティブは、ngx_http_geo_module ...
1. 画像の下にある数ピクセルの空白を削除するにはどうすればよいですか?コードをコピーコードは次のと...
目次スイッチも複雑なコードブロックもありませんPythonからのインスピレーション辞書を使用してスイ...
公式サイトからダウンロード: https://www.mysql.com MySQLの公式サイトにア...
mysqlは指定された期間内の統計データを取得します年別統計 選択 カウント(*)、 DATE_FO...
昨日、1年間使用していた Alibaba Cloud サーバーを購入しました。システムは Linux...
カルーセルはフロントエンド開発において比較的重要なポイントだと思います。ネイティブjsの知識ポイント...
序文前回の記事「MySQL ロック メカニズムの詳細説明」では、InnoDB のロック メカニズムに...