との差 '!' および「?」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
)ことをコンパイラに通知します。
ところで、Class
TypeScriptまたは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
またはundefined
firstNameの有効な値ではありません。
すべてのフィールドにデフォルト値が設定さ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
割り当てられていないことを文句を言いません。