Skip to content

"Property does not exist" error on union type even though all union members implement interface  #26204

Closed

Description

TypeScript Version: 3.0.1

Search Terms: Property does not exist union type implements interface

Code

interface IGameObject {
    onEvent?: (event) => void;
}

class Player implements IGameObject {}
class Enemy implements IGameObject {}

type MovingObjects = Player | Enemy;

const movingObjs: MovingObjects[] = [];

for (const obj of movingObjs) {
    // Error: "Property 'onEvent' does not exist on type 'MovingObjects[]'.""
    if (movingObjs.onEvent) {
        movingObjs.onEvent('someEvent');
    }
}

Expected behavior:
I would expect to be able to check if the method onEvent is present on the objects because they implement the interface, even though none of them implement the method yet. Some of them may implement it in the near future, so I want this check there to be safe. In my actual code, the interface also has non-optional properties that the classes do implement.

Actual behavior:
The compiler throws an error for "Property 'onEvent' does not exist on type 'MovingObjects[]'".

Playground Link:
https://www.typescriptlang.org/play/#src=interface%20IGameObject%20%7B%0D%0A%20%20%20%20onEvent%3F%3A%20(event)%20%3D%3E%20void%3B%0D%0A%7D%0D%0A%0D%0Aclass%20Player%20implements%20IGameObject%20%7B%7D%0D%0Aclass%20Enemy%20implements%20IGameObject%20%7B%7D%0D%0A%0D%0Atype%20MovingObjects%20%3D%20Player%20%7C%20Enemy%3B%0D%0A%0D%0Aconst%20movingObjs%3A%20MovingObjects%5B%5D%20%3D%20%5B%5D%3B%0D%0A%0D%0Afor%20(const%20obj%20of%20movingObjs)%20%7B%0D%0A%20%20%20%20%2F%2F%20Error%3A%20%22Property%20'onEvent'%20does%20not%20exist%20on%20type%20'MovingObjects%5B%5D'.%22%22%0D%0A%20%20%20%20if%20(movingObjs.onEvent)%20%7B%0D%0A%20%20%20%20%20%20%20%20movingObjs.onEvent('someEvent')%3B%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A

Related Issues:

Activity

  1. DanielRosenwasser commented on Aug 4, 2018

    @DanielRosenwasser
    Member

    Unfortunately, implementing an interface doesn't actually declare those members in the class. You'll need to explicitly declare onEvent (even as an optional member) in Player and Enemy.

  2. typescript-bot commented on Dec 14, 2018

    @typescript-bot
    Contributor

    This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

  3. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions