Brian Fernandez
Brian Fernandez

Reputation: 318

How to work with possible undefined values?

I'm trying to work with an optional parameter, if said parameter is not included when calling the function, it is assigned a value automatically.

When using this parameter in the global scope of the function I do not receive any error from the linter, the problem appears when I try to use it inside a forEach (I have only tried there).

The following code is an example of what happens:

interface opts {
  optionalParam?: number
}

const func = (options: opts): void => {
  // I assign a value to the optional parameter
  options.optionalParam ??= 100

  const obj = {
    test: 8
  }
  obj.test = options.optionalParam * obj.test // ✅ It works perfect

  const objs = [{
    test: 6
  }]
  objs.forEach((obj) => {
    obj.test = options.optionalParam * obj.test // ❌ The object is possibly "undefined".ts(2532)
               ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ
  })
}

I don't fully understand why in one place it detects it as undefined and in another it doesn't. 🤔

Upvotes: 2

Views: 37

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370689

TypeScript is not able to tell the difference between

objs.forEach(callback) // code that works with options

and

doSomethingAsynchronous().then(callback) // code that works with options

In the second case, it should be pretty clear why there could be a problem - you might assign an undefined value back to optionalParam before the async code runs. (options.optionalParam = undefined;) - the property is typed as number | undefined.

The first case with forEach has a similar problem because you're working with a callback.

One way to do this would be to remove the callback and use a for loop instead.

for (const obj of objs) {
  obj.test = options.optionalParam * obj.test
}

Another approach would be to extract optionalParam to a definitely-defined variable.

const func = (options: opts): void => {
  const optionalParam = options.optionalParam ?? 100;
  // proceed to reference optionalParam in the future
  // don't reference `options` again

or, more concisely

const func = ({ optionalParam = 100 }: opts): void => {

Upvotes: 2

Related Questions