Recently encountered a critical bug that I believe could have been identified with the right TypeScript setup. Struggling to come up with a suitable title, so please bear with me.
While initializing a widget app, similar to a chat app loaded by a parent app, we implement something like this:
type TParamsRoot = {
print: () => void;
}
type TParams = {
root?: TParamsRoot;
}
const init = (params: TParams = {}) => {
params.root ??= {
print: () => console.log('hello')
}
}
The concept here is that the parent app should pass on params
when loading the widget app, but in case it doesn't, a default value is assigned.
At some point in the code, I call params.root.print
as shown below:
const printConfig = () => {
params.root.print()
}
The initial issue was that TypeScript didn't warn me about params.root
possibly being undefined. I addressed this by enabling strict mode in my tsconfig and modifying the function to:
const printConfig = () => {
params.root?.print()
}
However, this wasn't enough because there was no error notification, leading to a bug. Even though I'm checking for params.root?
, I am still calling
print</code. To resolve this bug, I need to do:</p>
<pre><code>const printConfig = () => {
params.root?.print?.()
}
But how can I prompt TypeScript to alert me that print
might not be a function or even undefined? While init
guarantees it will always exist, I use this logic in a hook that is utilized in a component rendered before init
is triggered by the parent app, hence causing the bug.
Is my sole solution to define,
type TParamsRoot = {
print?: () => void;
}
It seems slightly misleading because if params.root
exists, then params.root.print
will also invariably exist.
In regard to the short-circuiting issue:
const params = {
root:
}
params.root?.print()
The above is what I relied on - indeed, it does short circuit. However, I have discovered that even when root
is passed, it may not always include print
. Problem resolved.
End of query.