microsoft / microsoft/TypeScript
Narrowing via property check fails when adding parent type to declaration
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Go
- Estrellas
- 111k
- Forks
- 14.4k
- Merge medio
- 1 d 19 h
- PR fusionados (30 d)
- 117
Descripción
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
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comienza con la reproducción proporcionada en TypeScript Playground y compara los tres ejemplos de foo, centrándote en cómo la asignación cambia el narrowing basado en comprobaciones de propiedades. El issue está terminado cuando el comportamiento sea consistente entre esos ejemplos y los errores never indicados se hayan resuelto o documentado intencionadamente.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- typescript
- Área
- compilers
- Tipo de issue
- Error
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Estado de actividad
- Estancado
- Claridad
- Necesita aclaración
- Aptitud para principiantes
- 25/100