2

Is it possible to destructure an object which comes from an function call without Typescript complaining?

File 1

  • React Component 1
...
let obj = null // <-- object initialization
...
useEffect(() => {
  obj = functionCall(...) // <-- function call that populates the object
}, [obj])
  • React component 2
const { key1, key2 } = obj // <-- object destructuring

Here I get the following complain from Typescript

  • Property 'key1' does not exist on type 'null'.
  • Property 'key2' does not exist on type 'null'.

How can I remove those warning?

2
  • Having obj declared and then filled in by a useEffect callback looks like a mistake. It may not be one, but it looks like one. See stackoverflow.com/questions/23667086/… and stackoverflow.com/questions/14220321/… for details. Depending on where that obj declaration is, it's either going to be re-created every time the component function runs, or it's going to be shared between all instances of the component. Both seem problematic. Commented Apr 29, 2021 at 9:04
  • The object is part of the global state of the app, set up as 'null' and I use useEffect to update the state with default value coming from a graphql call as those default values can be changed in the future. Commented Apr 29, 2021 at 9:07

3 Answers 3

2

Specify a type for obj:

let obj: null | {key1: sometype; key2: sometype; } = null;

Note that since obj may have the value null, you'll need a guard or a default value around that destructuring assignment:

if (obj) {
    const { key1, key2 } = obj;
}

or

const { key1, key2 } = obj ?? {key1: defaultForKey1, key2: defaultForKey2};

or

const { key1 = defaultForKey1, key2 = defaultForKey2 } = obj ?? {};

The difference between the last two is what happens if obj isn't null but key1 or key2 has the value undefined (if it's allowed to by the types).

Sign up to request clarification or add additional context in comments.

Comments

1

useEffect runs after your initial render - so on the first render obj will be null, and so TS is right to complain.

You need to check that obj is not null before de-structuring. Also, give it a type e.g

type MyType = { key1: string; key2: number; }; // for example

let obj: MyType | null  = null;

if (obj) {
  const { key1, key2 } = obj; // OK
} else {
  // In here, obj is null
}

Comments

0

Non-null assertion operator:

const { key1, key2 } = obj!;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.