microsoft / microsoft/TypeScript
[TS 4.2] Narrowing a union type is inconsistent using type guards on different member of union
Personne n'a encore pris cette issue.
- Langage dominant
- Go
- Étoiles
- 111k
- Forks
- 14.4k
- Merge moyen
- 1 j 19 h
- PR mergées (30 j)
- 117
Description
Bug Report
🔎 Search Terms
narrowing union type
🕗 Version & Regression Information
- This changed between versions 4.1.5 and 4.2.3
⏯ Playground Link
Playground link with relevant code
💻 Code
export type SuccessStatusCode = 200 | 201
export type FailureStatusCode = 400 | 401 | 402 | 403 | 500 | 502
interface HttpResponse<StatusCode extends SuccessStatusCode | FailureStatusCode> {
statusCode: StatusCode
}
interface LegacyApiResponse extends Partial<{ [key: string]: unknown }> {
statusCode?: never
}
type Success = HttpResponse<SuccessStatusCode> | LegacyApiResponse
type Failure = HttpResponse<FailureStatusCode>
type Result<S extends Success, F extends Failure = never> = S | F
declare function resultIsSuccess<S extends Success, F extends Failure>(r: Result<S, F>): r is S
declare function resultIsFailure<S extends Success, F extends Failure>(r: Result<S, F>): r is F
type TestResult = Result<{ success: true }, HttpResponse<403>>
declare const result: TestResult
export function test() {
if (resultIsFailure(result)) {
result // Inferred as HttpResponse<403>.
} else {
result // Inferred as { success: true }.
}
}
export function test2() {
if (resultIsSuccess(result)) {
result // Inferred as { success: true }.
} else {
result // Cannot infer, stay as TestResult.
}
}
🙁 Actual behavior
While test1 works fine, in test2, the else branch cannot narrow the type to HttpResponse<403>.
🙂 Expected behavior
test1 and test2 are just narrowing down result using complementary type guards, their behavior should be consistent.
And they are consistent in 4.1.
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par la reproduction liée dans TypeScript Playground et comparez les guards complémentaires resultIsSuccess et resultIsFailure dans test() et test2(). Suivez la manière dont le vérificateur de types affine les branches else ; le travail est terminé lorsque les deux exemples affinent systématiquement le membre complémentaire de l’union comme prévu dans les versions de TypeScript signalées.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- typescript
- Domaine
- compilers
- Type d'issue
- Bug
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Activité
- À l'abandon
- Clarté
- Plutôt claire
- Accessibilité débutants
- 35/100