microsoft / microsoft/TypeScript
Narrowing via property check fails when adding parent type to declaration
Nessuno ha ancora preso questa issue.
- Lingua principale
- Go
- Stelle
- 111k
- Fork
- 14.3k
- Merge medio
- 2g 4h
- PR unite (30g)
- 132
Descrizione
TypeScript Version: 3.8.3
Search Terms:
- property check refinement
Expected behavior: No error, type is narrowed to SubA.
Actual behavior: Type is narrowed to never and produces an error.
Related Issues:
Code
This code type checks:
interface Base {
base: number;
}
interface SubA extends Base {
a: string;
other: boolean;
}
interface SubB extends Base {
b: string;
}
function foo(x: SubA | SubB | null) {
x = x || {base: 1, b: 'b'};
if (x && 'a' in x && x.a == 'str') {
x.other; // ok
}
}
A very tiny tweak (adding Base | to the parameter type) breaks things, though:
function foo(x: Base | SubA | SubB | null) {
x = x || {base: 1, b: 'b'};
if (x && 'a' in x && x.a == 'str') { // <-- Property 'a' does not exist on type 'never'. (2339)
x.other; // <-- Property 'other' does not exist on type 'never'. (2339)
}
}
This makes some sense since foo could be called with something assignable to Base that has an a but is not specifically a SubA. But what doesn't make sense to me is that removing the assignment on the first line makes the error go away:
function foo(x: Base | SubA | SubB | null) {
if (x && 'a' in x && x.a == 'str') { // ok
x.other; // ok
}
}
That assignment seeming has no bearing on if statement (the default value doesn't have an a property). So why does it affect the inferred type in it?
Either the second and third example should both error or neither of them should.
Output
"use strict";
function foo(x) {
x = x || {base: 1, b: 'b'};
if (x && 'a' in x && x.a == 'str') {
x.other;
}
}
Compiler Options
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"strictBindCallApply": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"alwaysStrict": true,
"esModuleInterop": true,
"declaration": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"moduleResolution": 2,
"target": "ES2017",
"jsx": "React",
"module": "ESNext"
}
}
Playground Link: Provided
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia con la riproduzione fornita in TypeScript Playground e confronta i tre esempi di foo, concentrandoti su come l'assegnazione modifica il narrowing basato sui controlli delle proprietà. L'issue è completata quando il comportamento è coerente tra questi esempi e gli errori never segnalati sono risolti o documentati intenzionalmente.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- typescript
- Ambito
- compilers
- Tipo di issue
- Bug
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Stato di attività
- Ferma
- Chiarezza
- Da chiarire
- Idoneità per principianti
- 25/100