web-dev-qa-db-ja.com

NestjsでDTOの特定の列挙値を禁止する

私の「AppState」列挙には、次の可能な列挙値があります。

export enum AppState {
  SUCCESS,
  ERROR,
  RUNNING
}

[UpdateAppStateDTOappStateを使用します。これは[〜#〜] running [〜#〜]以外のすべての列挙値を受け入れる必要があります。

export class UpdateAppStateDTO {
  @IsEnum(AppState)
  @NotEquals(AppState.RUNNING) // Doesn't work properly
  public appState: AppState;
}

ルートについては、この例があります

  @Patch()
  public setState(@Body() { appState }: UpdateAppStateDTO): void {
    console.log(appState);
  }

リクエストの本文が空であるか、appStateの「foobar」などの無効な列挙値がある場合、400が返されます。

問題は、「RUNNING」を送信したときに、400ではなく200が引き続き取得されることです。

この動作を防ぐにはどうすればよいですか?

3
user11668595

問題は、「RUNNING」を送信しても、400ではなく200が引き続き取得されることです。

次のように、リクエストペイロードの値としてstring(!) "RUNNING"を使用しているようです:

_{ appState: "RUNNING" }
_

この場合、IsEnumNotEqualsはどちらもペイロードを有効と見なします。

それはなぜですか?

まず最初に 数値列挙はTypeScriptによって逆マッピングされます なので、列挙は内部的に(JavaScriptオブジェクトとして)次のように表されます。

_{
  '0': 'SUCCESS',
  '1': 'ERROR',
  '2': 'RUNNING',
  SUCCESS: 0,
  ERROR: 1,
  RUNNING: 2
}
_

ここで、クラスバリデーターのisEnum()次のようにコーディングされます

_isEnum(value: unknown, entity: any): boolean {
    const enumValues = Object.keys(entity)
        .map(k => entity[k]);
    return enumValues.indexOf(value) >= 0;
}
_

列挙型が逆マップされているため、isEnum('RUNNNING', AppState)はtrueを返します。

同時にNotEquals、これは そのようにコーディングされています ...

_notEquals(value: unknown, comparison: unknown): boolean {
    return value !== comparison;
}
_

文字列 'RUNNING'を_AppState.RUNNING_(_2_と同等)と比較し、これは_'RUNNING' != 2_以降有効であると結論付けます。

つまり、ペイロード_{ appState: "RUNNING" }_がステータスコード400ではなく200になる理由がわかります。

この動作を防ぐにはどうすればよいですか?

列挙値_AppState.RUNNING_は_2_と同等であるため、リクエストを行うときは、ペイロードで_2_の数値を使用する必要があります。

_{ appState: 2 }
_

上記の場合、クラスバリデーターのNotEqualsバリデーターは、次の内容を含む応答でリクエストを正しく拒否します。

_"constraints": {
    "notEquals": "appState should not be equal to 2"
}
_
0
B12Toaster