-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Code flow analysis isn't smart enough #8270
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
I'm also experiencing the same error as the second example using export function patch<R>(path: string, options?: HTTPOptions): Promise<HTTPResponse<R>> {
options = options || {};
options.method = 'PATCH'; // error options can be null or undefined
let req = new HttpRequest<R>(path, options);
return req.request();
} In addition, the |
@pleerock Regarding the first issue, control flow analysis doesn't consider a type guard to hold across a callback (because the callback could happen at any time, including outside the guarded block). This is different and more conservative from what we've previously done, and we're certainly open to feedback about whether it is too conservative. Meanwhile, you probably want to capture the guarded variable in a local and then reference that in the callback: if (options.leftJoin) {
const leftJoin = options.leftJoin;
Object.keys(leftJoin).forEach(key => {
qb.leftJoin(leftJoin[key], key);
});
...
} Regarding your second example, I can't tell how @tinganho Your example compiles fine for me (but I suspect you have an older nightly build). |
@basarat are you on the same typescript version as me? Because it looks weird that I get this error and you are not. I used same code as you and I get an error. Proof: |
@ahejlsberg thank you, got the problem of the first issue. For the second issue I have same code as basarat which does not compile |
@pleerock
The strange thing is that it doesn't work on my IDE VSCode Insider: I have defined in my workspace settings: {
"typescript.tsdk": "/usr/local/lib/node_modules/typescript/lib",
} |
It appears the current typescript@next (1.9.0-dev.20160424) still doesn't contain the control flow type analysis logic (there's no @mhegazy Mohamed, any ideas? |
Yes got it now. |
Looks like we have not published a nightly since 4/12. the script is publishing without updating. looking into it. |
@pleerock I am actually on nTypeScript https://github.com/TypeStrong/ntypescript which is just a build of TypeScript/master with some automation I did before official |
We've identified and fixed the issue with the nightly build server. Tonight's build should be good and will contain the control flow type analysis logic. |
confirming that it works with the last build |
@pleerock thanks for the confirmation. |
@ahejlsberg @yuit This doesn't work in nightly TypeScript - is it a related issue or should I file as a new bug? let maybeNumber: number | undefined;
(function () {
maybeNumber = 1;
})();
if (maybeNumber) {
maybeNumber++; // -> says that type of `maybeNumber` is always `nothing`, not even `number | undefined` anymore
} |
@RReverser this is not covered in OP. control flow analysis is localized, and does not track side effects from other functions. feel free to file a new issue though. |
@mhegazy Well, I don't expect it to be smart enough to refine |
Filed at #8381. |
the issue is it does not know about the side effects. you would want it to catch something like: let maybeNumber: number | undefined;
if (maybeNumber) {
maybeNumber++; // there is no way the control flow would reach here.
} |
@mhegazy Hmm, can't it assume that declared variable type was preserved on unknown side effects? |
the declared variable type is always there. but then control flow "narrows" it down. so: let maybeNumber: number | undefined;
maybeNumber // it is undefined here, though it is defined as a number | undefined, there are no initialization to a non-undefined value.
maybeNumber = 1; // it is number definitely
maybeNumber ++; // allowed, as it is definitely a number
if (maybeNumber === undefined) {
maybeNumber // here it is nothing, i.e. there is no way for the control flow to reach here, as it was a number, and number does not include undefined.
} |
@mhegazy Yeah, I understand why in: let maybeNumber: number | undefined;
if (maybeNumber) {
maybeNumber++; // there is no way the control flow would reach here.
} it fails - it's obvious that control flow won't reach here because However, I would expect compiler to assume let maybeNumber: number | undefined;
// Control flow figured that: maybeNumber === undefined
(function () {
maybeNumber = 1;
})(); // --> oops, unknown side effects
// Revert maybeNumber to initial `number | undefined` to cover all possibilities due to the unknown side effects in the flow
if (maybeNumber) {
// Control flow: can refine to `number` again here
maybeNumber++;
} |
yup, i think we are saying the same thing. and that is what #8381 is tracking. |
@mhegazy Cool, thanks. Just wanted to be sure we're on the same page / I'm not getting anything wrong. |
Hi, I hit this error too. I understand the reasoning behind not carrying the reduced type over closures but non the less it looks very counter intuitive. My case is with returning a closure, which should be safe. function getLengthLambda(x: any[]|null) {
if (!x) {
return () => 0;
}
return () => x.length + 1; // <--- error TS2531: Object is possibly 'null'
}
getLengthLambda([]); |
I have just encountered the problem with _.isEmpty (underscore safe check, will shortcut on undefined and null): if (_.isEmpty(childrenDescription)) {
return null;
}
// Here I get TS2531: Object is possibly 'null' or 'undefined`, which is wrong
return childrenDescription.map(createChild); As for now I'm switching from elegant underscore to sth like if (!childrenDescription || childrenDescription.length === 0) // blehhhh tsc 2.0.3 |
@108adams It's just a problem of poor definition, not of TypeScript itself. For example, if I define helper like
it can already catch these cases and control flow will know that anything after the check is at least non-null. |
typescript version: Version 1.9.0-dev.20160424
first looks like a bug:
Gives TS2531: Object is possibly 'null' or 'undefined'., however error is not expected because of the

if (options.leftJoin)
check above.second:
Gives same TS2531: Object is possibly 'null' or 'undefined'.. Looks like expected behaviour because of original type of the options object. Solution is to define variable with a new type and without undefined. Maybe there is a smarter way to do it?

The text was updated successfully, but these errors were encountered: