-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Support strict mode #505
Support strict mode #505
Conversation
Under strict mode, while the TypeScript compiler seems to handle it fine, returning Lines 182 to 184 in 4772c14
Were causing The long term fix is to improve the resilience of the code in |
const depModule = FileModule.load(resolved); | ||
depModule.compileAndRun(); | ||
return depModule.exports; | ||
util.assert(resolved != null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These null assert checks are redundant when using the bang operator. Suggest removing the assert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ry just to make it clear, the not null assertion operator (!
) in TypeScript only says "I know what I am doing" and does not actually change the runtime behaviour in any sense. Given that, should we still remove it, or is it more valuable to actually put a comment in the assert to make the potential throw more logical.
As a side note, the TypeScript team recently closed the issue that would allow assert
like calls to affect CFA analysis (microsoft/TypeScript#8655) in lieu of microsoft/TypeScript#10421 which might allow authoring of some sort of function(s) that would allow this pattern to affect CFA and therefore the type past this point in the block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kitsonk Oh sorry - I thought it threw an exception. In that case ignore my comments and keep the asserts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Just a few comments.
js/os.ts
Outdated
} | ||
assert(fbs.Any.ReadFileSyncRes === baseRes.msgType()); | ||
const res = new fbs.ReadFileSyncRes(); | ||
assert(baseRes.msg(res) != null); | ||
return new Uint8Array(res.dataArray()); | ||
// TypeScript cannot track assertion above, therefore not null assertion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this comment is wrong - because res.dataArray()
is not checked as null?
const bb = new flatbuffers.ByteBuffer(new Uint8Array(resBuf)); | ||
// TypeScript does not track `assert` from a CFA perspective, therefore not | ||
// null assertion `!` | ||
const bb = new flatbuffers.ByteBuffer(new Uint8Array(resBuf!)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These null assert checks are redundant when using the bang operator. Suggest removing the assert.
const bb = new flatbuffers.ByteBuffer(new Uint8Array(resBuf)); | ||
// TypeScript does not track `assert` from a CFA perspective, therefore not | ||
// null assertion `!` | ||
const bb = new flatbuffers.ByteBuffer(new Uint8Array(resBuf!)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These null assert checks are redundant when using the bang operator. Suggest removing the assert.
mod.compileAndRun(); | ||
assert(mod != null); | ||
// TypeScript does not track assert, therefore not null assertion | ||
mod!.compileAndRun(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These null assert checks are redundant when using the bang operator. Suggest removing the assert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ry @kitsonk FYI, you can avoid the bang if you create a new assertNotNull
function like so:
function assertNotNull<T>(val: T | null | undefined, msg = "assert not null"): val is T {
if (val === null || val === undefined) {
throw Error(msg);
}
return true;
}
See this question on stackoverflow for more info: https://stackoverflow.com/a/46700791/266535
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@styfle that doesn't work the way you think it would work, because TypeScript does not know that the code past that point is narrowed without some block scoping. For example, if this is run under --strictNullChecks
:
function assertNotNull<T>(val: T | null | undefined, msg = "assert not null"): val is T {
if (val === null || val === undefined) {
throw Error(msg);
}
return true;
}
declare const foo: string | undefined;
declare function bar(val: string): void;
foo; // string | undefined
assertNotNull(foo);
foo; // string | undefined
bar(foo); // maybe undefined
Also see microsoft/TypeScript#8655 which explains that problem is not currently supported by TypeScript.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kitsonk Oh right, you would need an if
statement for the assert for it to narrow the type as not null.
See this playground.
But it's still safer than using !
in my opinion 😅
// different, so we have to return an "empty" resolved module | ||
// TODO: all this does is push the problem downstream, and TypeScript | ||
// will complain it can't identify the type of the file and throw | ||
// a runtime exception, so we need to handle missing modules better |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plan to deal with this under #509
moduleName: string | null; | ||
filename: string | null; | ||
sourceCode: string | null; | ||
outputCode: string | null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this not the same thing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Under strict mode, undefined
and null
are incompatible. Because when we create the object literal, we are using functions that return null
but always defining the properties. We could retain that optional properties, but if we use null
for a not present value, we have to include it as a potential type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok - makes sense
js/assets.ts
Outdated
@@ -96,5 +96,5 @@ export const assetSourceCode: { [key: string]: string } = { | |||
"types.d.ts": typesDts, | |||
|
|||
// TODO(ry) Remove the following when possible. It's a workaround. | |||
"msg_generated.d.ts": "", | |||
"msg_generated.d.ts": " ", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to be rebased
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - great clean up - thank you
Bumped versions for 0.256.0 Co-authored-by: littledivy <littledivy@users.noreply.github.com>
Resolves #504
This PR sets
--strict
when compiling the internal TypeScript for Deno and makes the necessary changes to support that. There were a couple issues around strict null checking that were fixed, but most were cases where TypeScript could not determine that a value was defined, but it was known to be defined. In those cases I used the not null assertion operator (!
) and inserted a comment. Not all of my assumptions might of been accurate though.