-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Partial type is not narrowed even when its only property is successfully narrowed as being defined #29827
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The check will only narrow the This for example works: type T = { content: string[] };
declare function getData(): T | { content?: undefined};
const partial = getData();
let data: T;
if (partial.content) {
data = partial; // ok
data = { content: partial.content }; //also ok
} I am pretty sure this is the current designed behavior, but I have seen similar questions come up on SO. The basic expectation being that if a field is narrowed, then, on assignment of the object, that field narrowing is taken into account for compatibility. This also fails, perhaps better illustrating what I am trying to explain: type T = { content: "A" | "B" };
declare let data: T;
if (data.content == "A") {
let justA : { content: "A" } = data // also an error
} This information should already be available and the assignment seems safe. |
The latter example isn't safe because of aliasing, which is non-trivial to track. type T = { content: "A" | "B" };
declare let data: T;
if (data.content == "A") {
let justA : { content: "A" } = data;
data = { content: "B" };
} A type |
@jack-williams Fair enough. This doesn't work either and it feels like it should: type T = { content: "A" | "B" };
declare let data: T;
if (data.content == "A") {
let justA : { content: "A" } = { ...data }; // still an err
} Here we are copying the data to a new object so changing the value should not be an issue. |
Thanks @jack-williams, that makes it pretty clear why the behavior I was expecting can't be possible... it seems so obvious in retrospect! type T = { content: string[] };
declare let partial: Partial<T>;
if (partial.content) {
let data: T = partial;
delete partial.content; // `data` is now mistyped
} |
@dragomirtitian Yep, operationally that should work. I think type-checking that is non-trivial under the current infrastructure. You would need to synthesize property access nodes to get the narrowed type of every field and then reconstruct that on the spread, I think. I'm also not sure what would happen in the case of generics: function foo<X extends T>(x: X): X {
if (x.content === "A") {
return { ...x };
}
return x;
} Doing anything funny with the spread might break existing code that expects the spread to return the exact same type back. |
TypeScript Version: 3.4.0-dev.20190208
Search Terms:
Partial narrow
Code
Expected behavior: No errors. Specifically, the
if (partial.content)
check narrowspartial
fromPartial<T>
toT
.Actual behavior: The following error:
Playground Link: playground link
Related Issues: #29496
The text was updated successfully, but these errors were encountered: