How to ignore "missing the following properties" error in TypeScript?

Viewed 2460

I create an Obj like this.

interface obj {
  x: number;
  y: number;
  deep?: {
    z: number;
  };
}

let obj: obj = {}; // Type '{}' is missing the following properties from type 'obj': x, y 
    ^^^

I could use optional field.But when I want to access optional field I have to use nullish operator.

// But I don't want to use nullish operator
obj.deep?.z; 

// without nullish operator.
obj.deep.z;  // Object is possibly 'undefined'.
^^^^^^^^
// this is valid unless some condition (like is async function where its not "undefined" anymore);

Because optional field required nullish operator.I need some way to ignore "required properties" type error.

1 Answers

You can use a type assertion to tell the compiler that your value {} is an obj:

let obj = {} as obj;

Type assertions are useful in situations where you know more about the type of a value than the compiler can verify. You just tell it what you know about the value and the compiler believes you (sometimes this takes an extra assertion like as unknown as obj, but you can eventually make the compiler believe you). This shifts the burden of maintaining type safety away from the compiler and onto you. Since the compiler just believes you, it will not catch the situation where you lie to it. The value {} is not a valid obj, and so by using a type assertion to say that it is, you are telling the compiler a lie.

This isn't as bad as I might be making it sound; if you intend to immediately initialize obj so that, by the time anyone else interacts with it, it will be a proper instance of obj, then it's a white lie. You just want the compiler to "look the other way" while you're initializing the variable:

let obj = {} as obj; // this is a lie
// DANGER ZONE
obj.x = 1;
obj.y = 2;
obj.deep = {} as { z: number };
obj.deep.z = 123;
// END DANGER ZONE
// obj is no longer a lie
obj.deep.z.toFixed(); // no error

But you should be careful with this sort of approach. If you fail to properly initialize the variable, then it will be an issue at runtime. For this reason I usually try to refactor my code so that there's no period of time when it's only partially configured:

let badObj = { x: 1, y: 2 }
let deep = { z: 3 }; // get this from somewhere else, awaited or whatever
let goodObj: obj = Object.assign(badObj, { deep }); // okay

Okay, hope that helps; good luck!

Playground link

Related