Home > Mobile >  Union type is not being detected
Union type is not being detected

Time:06-01

I have the following types defined:

export type Property =
  | BooleanProperty
  | NumberProperty
  | IntegerProperty
  | StringProperty
  | ObjectProperty
  | ArrayProperty;

export interface OneOf {
  oneOf: PropertyOrKeyword[];
}
export interface AnyOf {
  anyOf: PropertyOrKeyword[];
}
type Keyword = OneOf | AnyOf;
export type PropertyOrKeyword = Property | Keyword;

In my code, I then have this:

const val = parent[objName]; // This is a PropertyOrKeyword type
if ("oneOf" in parent[objName]) {
  const index = val.oneOf.findIndex(
    (obj: Property) => obj.title === title
  );
  val.oneOf[index] = ref(title);
}

When I hover over val.oneOf, however, I see the following error:

Property 'oneOf' does not exist on type 'PropertyOrKeyword'.
  Property 'oneOf' does not exist on type 'BooleanProperty'.

It seems that maybe there are too many types being unioned, and TypeScript isn't able to detect that oneOf is a field on one of those types? Or am I doing something weird here? Seems to me that this should be working, and the in phrase should help TypeScript discover that val is of the OneOf type.

Am I missing something here? Does it have to do with the recursive nature of the types?

CodePudding user response:

TypeScript cannot understand that val and parent[objName] are the same object, even if the assignment is at the line before the check. You should check directly the val property.

const val = parent[objName]; // This is a PropertyOrKeyword type
if (typeof val === "object" && "oneOf" in val) {
  const index = val.oneOf.findIndex(
    (obj: Property) => (obj as ({title: string})).title === title
  );
  val.oneOf[index] = ref(title);
}

Here is a complete TS Playground solving your code.

As a side note, you should also check that the obj has the title property or casting it to somewhat like { title: string } before comparing the value of the title property in your findByIndex callback

  • Related