1

I was sure it was working few versions back, TypeScript supported operator in to test existence of a field and narrowed/modified the type accordingly.

How to rewrite following code in a type-safe manner (e.g. no any)?

const t: object = Math.random() > 0.5 ? { x: 1 } : { y: true };
if ('y' in t && typeof t.y === 'boolean') {
    console.log(t.y ? 'Y TRUE':'Y FALSE'); // error
} else if('x' in t) {
    console.log('X =', t.x); // error
} else {
    console.log('?', t);
}

All lines with field access of t are in red, TS compiler complaining that given field doesn't exist on type object, even though in both cases on the line before the in operator confirmed the field is present and thus the type should have been updated.

I also tried unknown (+ typeof ... === 'object'), that didn't work either.

1
  • 1
    Note this works just fine if you remove the explicit widening of t to : object. The inferred type ({ x: number; y?: undefined; } | { y: boolean; x?: undefined; }) is a union that can be discriminated with the in type guard: typescriptlang.org/play/… Commented Jul 28, 2020 at 15:18

1 Answer 1

1

Property x and y are missing in object type, so typescript complains.

You need to define custom type:

type ExAndWhy = {
  x?: number;
  y?: boolean;
}
const t: ExAndWhy = Math.random() > 0.5 ? { x: 1 } : { y: true };

If you're looking for "object" type that can hold anything, it is this:

type Anything = {
  [key: string]: any;
};

const t:Anything = { x: 1, y: true};
Sign up to request clarification or add additional context in comments.

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.