-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Proposal: optionally declared variables #23602
Comments
So the expectation here is that lib.d.ts would have that said, the proposal itself has merit. I would just say the |
@mhegazy I'm not sure, but I believe the semantics need to be different from e.g. Having said that... while I think the proposal is good within its scope, I don't think it's very important, relative to https://github.com/Microsoft/TypeScript/issues. |
I agree. I would expect this proposal would be used to create a derivative versions of The derivative versions could be created by a script that rewrites
Putting it after the name would be more consistent with existing syntax, so I can see the benefit of that. I'm curious if the semantic differences with optional interface fields would be undesirable.
Compared to an optional interface field
Perhaps because since a |
Consider the difference in meaning for optional function parameters as well. |
Possibly another use case of |
You could have or add something like this as well:
Reference: |
I believe I'm going to be satisfied with #29332 and a lint rule to ban global access for things like const { window } = globalThis;
if (window) {
// do something with window
} |
Scenario
When writing code that will run in both Node.js and browser environments (e.g. a React component compatible with SSR), it's sometimes necessary that part of the code only executes in one environment and not the other.
A few browser-only examples:
document.querySelector()
to find an element in the DOM.document.title = "new title"
to update the page title.To avoid executing these in Node.js, the following pattern is used:
Now the developer needs to configure TypeScript to include the types for
document
. It basically boils down to them deciding whether or not to includedom
in thelib
compiler option.(
dom.d.ts
is distributed with TypeScript and includes:)Unfortunately both options have compromises:
document
won't be declared, and TypeScript will warnCannot find name 'document'.
document
will be declared as aDocument
, but not asDocument | undefined
, sostrict-type-predicates
will complain that the check is unnecessaryA motivated developer may choose to fork
dom.d.ts
and add| undefined
to all of the global variable declarations, and satisfystrict-type-predicates
.However one final piece of safety is still missing: ensuring
typeof document !== "undefined"
is used, rather thandocument !== undefined
. At runtime ifdocument
(or any name) isn't declared, and is used outsidetypeof
, aReferenceError
is thrown. For this reason it's necessary to always choosetypeof
when performing environment "sniffing".TypeScript currently cannot model "optionally declared variables", where a variable "might" be declared. Without this, TypeScript doesn't have enough information to warn about code that may throw
ReferenceError
.Proposal
Introduce new syntax and type system concepts to allow the "optional declaration" of variables. Emit would be unaffected.
Proposed syntax:
This is distinct from:
In the first case, it's describing that
window
may not be declared, and referencingwindow
may throw aReferenceError
. In the second case,window
is always declared, but might have the valueundefined
.Implementation:
?
followingdeclare
.DeclareKeyword
or a newOptionalDeclareKeyword
).typeof
guards.declare? var document: Document
), e.g. when hovering a name in VS Code.Shortcomings:
typeof window !== "undefined"
guard could safely grant access to other browser globals (e.g.document
,performance
, etc). This current proposal would require separatetypeof
checks for each global.The text was updated successfully, but these errors were encountered: