Vyhledávání na webu

generics - Typescript jakékoliv číslo kromě X


Shrnutí:

Je tento typ nějak možný v TS? Exclude<number, 200 | 400> ("jakékoliv číslo kromě 200 nebo 400")

Mám následující případ použití. Mám typ odpovědi, který je generický:

type HttpResponse<Body = any, StatusCode = number> = {
  body: Body
  statusCode: StatusCode
}

A rád bych použil stavový kód jako rozlišovací znak:

// Succes
type SuccessResponse = HttpResponse<SomeType, 200>
// Known error
type ClientErrorResponse = HttpResponse<ClientError, 400>
// Anything else, generic error, issue is with the status code here.
type OtherErrorResponse = HttpResponse<GenericError, Exclude<number, 200 | 400>>

// The response type is a union of the above
type MyResponse = SuccessResponse | ClientErrorResponse | OtherErrorResponse 

Když používám typ MyResponse, rád bych použil stavový kód jako rozlišovač, např.:

const response: MyResponse = ...

if(response.statusCode === 200) {
  // response is inferred as SuccessResponse => body is inferred as SomeType
} else if(response.statusCode === 400) {
  // response is inferred as ClientErrorResponse => body is inferred as ClientError
} else {
  // response is inferred as OtherErrorResponse => body is inferred as GenericError
}

Nicméně to takto nefunguje, protože Exclude<number, 200 | 400> je totéž jako prosté number. Jak to vyřešit? Je typ "jakékoliv číslo kromě 200 nebo 400" vůbec možný v TypeScriptu? Existují nějaké jiné kreativní řešení?

Odpověď č. 1

V tuto chvíli to není možné.

Viz: https://github.com/microsoft/TypeScript/issues/15480


Exclude<number, 200 | 400> nefunguje, protože TypeScript sleduje pouze to, čím něco je, a nikdy nesleduje to, čím není. Aby vyloučení některých hodnot z nekonečné řady fungovalo, musel by TypeScript vygenerovat unii se všemi možnými hodnotami kromě těch, které chcete vyloučit. To by byla unie nekonečné délky (protože nekonečno minus 2 se rovná nekonečnu)


To se řeklo, seznam HTTP stavových kódů je vlastně konečný. Takže nejlepší způsob je pravděpodobně vytvořit sjednocení všech možných hodnot a použít ho:

type HTTPStatusCode = 100 | 101 | 102 | 103 | 200 | 201 | 202 | ...

Teď by to mělo fungovat dobře:

Exclude<HTTPStatusCode, 200 | 400>

Související články