kfi kfi - 3 months ago 13
TypeScript Question

Typescript multiple type parameter

I can't figure out how to access the pos propery.


error TS2339: Property 'pos' does not exist on type '{ pos: RoomPosition; } | RoomPosition'.


public moveTo(target: RoomPosition | { pos: RoomPosition }, opts?: FindPathOpts): number {
..
if (target instanceof RoomPosition && !target.isEqualTo(destination.x, destination.y)) {
..
} else if (!target.pos.isEqualTo(destination.x, destination.y)) {
..
}

Answer

See https://www.typescriptlang.org/docs/handbook/advanced-types.html

When you use a union type, you can only access properties that are common to both types - as they are the only properties Typescript knows for sure will be on the variable.

To access the variable that is only available on a given Type, you need to use a type assertion. You can use an explicit type assertion e.g.

if (target instanceof RoomPosition && !target.isEqualTo(destination.x, destination.y)) {
  ...
} else if (<{pos:RoomPosition}>target.pos.isEqualTo(destination.x, destination.y)) {
  ...
}

You should also restructure your code a bit, as the else condition may be triggered even if target is a RoomPosition, but it is not equal to the destination, and that may cause a runtime issue accessing .pos in the else clause. The following is safer:

if (target instanceof RoomPosition) {
    if (!target.isEqualTo(destination.x, destination.y)) {
      ...
    }
} else if (<{pos:RoomPosition}>target.pos.isEqualTo(destination.x, destination.y)) {
  ...
}

It might also be worth defining a named type or interface to represent {pos:RoomPosition}.

There are other syntactic ways of achieving the same thing - see the doc above for user defined type guards and some of the other mechanisms for working with union types.