Home > other >  How to check if object has undefined values with a helper function using typescript?
How to check if object has undefined values with a helper function using typescript?

Time:04-13

I was wondering if it is possible to check for undefined values in object with typescript using helper function?

type Page = {
  hero?: {
    title?: string
  },
  about: {
    title?: string,
  }
}

const obj: Page = {
  hero: undefined,
  about: {
    title: 'hello',
  }
}

const check = <T extends Object,>(obj: T, values: Array<keyof T>) => {
  values.forEach((value)=>{
    if (!obj[value]){
      throw new Error(`${value} is missing!`)
    }
  })
};

check(obj, ['hero'])

obj.hero.title

but it still says that " Object is possibly 'undefined' " . Is there any way I can achieve something like that with typescript?

EDIT: I am aware that I can explicitly check for that property using ? . I wonder if it is possible to make ts happy using helper function as described above.

CodePudding user response:

You can make helper function like this. It is a bit hacky but I think it kind of does what you want.


type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }

const check = <T extends Object, V extends Array<keyof T>>(obj: T, values: V): WithRequired<T, V[number]> => {
  values.forEach((value)=>{
    if (!obj[value]){
      throw new Error(`${value} is missing!`)
    }
  })

  return obj as WithRequired<T, V[number]>;
};

const objChecked = check(obj, ['hero'])

objChecked.hero.title

Playground

CodePudding user response:

Your problem is that you're confusing types with values.

When you write:

check(obj, ['hero'])
obj.hero

You are thinking something like "ok, so we know obj.hero can't be undefined", because you checked the value.

But the compiler can't see runtime values, it only works with types, and the type of the argument to check is Array<keyof T> it doesn't (and can't!) know that you checked that specific key that you're referencing on the next line.

Same deal with the thrown error, the compiler has limited ability to prove things about runtime side effects like thrown errors. It can do basic control flow analysis to realize that e.g. code after a throw is unreachable, but don't expect too much of it.

There isn't really any need for a helper function for this anyway:

if (obj?.hero !== undefined) {
  console.log(obj.hero.title); // works!
}

will suffice.

Playground

Note that per my comment on your question, you really want to check for undefined if that's what you're worried about: with your original code the following (non-exhaustive) list of values will throw an error: null, undefined, 0, NaN, '', false and so on.

CodePudding user response:

Either use ? or if condition.

In JSX, use ternary.

{obj?.hero ? {use of hero} : null}

OR

In Functions, use if.

if (obj && obj.hero) {Your code here for hero}
  • Related