との差 '!' および「?」TypeScriptで
Class Employee {
firstName: string;
lastName!: string;
middleName?: string;
}
Employeeクラスのこれらの3つの異なるフィールドの違いは何ですか?
実例
回答
?その位置でマークプロパティオプション。
!その位置には、明確な割り当て表明。これは、null以外のアサーション演算子の宣言レベルのバージョンのようなものですが、式ではなくプロパティ(変数でも使用できます)で使用されます。
この例には、2つ(またはおそらく3つ)のエラーがあります。
Classする必要がありclassます; JavaScriptとTypeScriptでは大文字と小文字が区別されます。初期化子
firstName(または無条件に割り当てるコンストラクター)が必要です。!上には、lastName活字体伝えlastName間違いなくあなたが取得しているエラーの種類を抑制し、割り当てられますfirstNameが、(この例では)何も実際には行われません使用していることを割り当て!が約束することは、あなたがやっていることを確認するために知って活字体を。
編集:後でリンクしたコードは、上記の#1と#2を扱いますが、#3は扱いません。TypeScriptlastNameは、割り当てられていないことを警告せず、値が文字列であると想定しますが、実際には文字列がないため、値を読み取るとundefined。になります。
それらはTypeScriptのドキュメントによく隠されています。
?はインターフェイスで説明されており、オプションのプロパティをマークします。
!は明確なアサーション演算子です。TypeScriptの分析で検出できない場合でも、プロパティが設定されている(nullまたはではないundefined)ことをコンパイラに通知します。
ところで、ClassTypeScriptまたはJavaScriptキーワードではなく、その位置でエラーが発生します。クラスを宣言するためのキーワードはclassです。活字体とJavaScriptの識別子とキーワードは大文字と小文字が区別されます(Classとclass異なるものです)。
コンパイラオプションがある場合 strictNullChecks: false
あなたが持っている場合はstrictNullChecks: false、あなたの中でtsconfig.json、彼らは持つので、全く同じでstrictNullChecks、すべてのフィールドがNULLまたは有効な値として未定義ことを無効にする手段を。
コンパイラオプションがある場合 strictNullChecks: true
class Employee {
firstName: string;
lastName!: string;
middleName?: string;
}
firstName: stringつまり、でfirstNameある必要がありstringます。nullまたはundefinedfirstNameの有効な値ではありません。
すべてのフィールドにデフォルト値が設定さundefinedれ、エラーが発生しますProperty 'firstName' has no initializer and is not definitely assigned in constructor
エラーを消音するには、宣言をに変更するかfirstName: string = 'Some default value'、コンストラクターを追加して、コンストラクターでその値を割り当てる必要があります。
constructor() {
this.firstName = 'some default value';
}
さあ!構文。lastName!: stringように構文が似ているlastName: stringという点で、それは基本的に唯一と言っているstringだけ許さタイプです。nullとundefinedは許可されていません。しかし、それは明確な割り当てエラーについてコンパイラを沈黙させます。次のコードがあるとしましょう。
クラス従業員{firstName:文字列; lastName !:文字列; ミドルネーム?:文字列;
constructor() {
// This will silence the compiler about first name not initialized
this.firstName = 'some default value';
// The compiler cannot tell that lastName is assigned in init() function
this.init();
}
private init(): void {
this.lastName = 'some default value';
}
}
前のコードでlastNameは、は呼び出しconstructorを介して確実に割り当てられていthis.init()ます。しかし、コンパイラはそれを知ることができません。したがって、!を追加します。基本的にはコンパイラに「黙って、自分が何をしているのか知っている」と言っています。コードの正確さを保証するのはあなた次第です。
middleName?: string構文について。これはmiddleName: string | undefined;とまったく同じです。すべての値のデフォルト値はundefinedであるため、コンパイラはmiddleName割り当てられていないことを文句を言いません。