1
/** Represents a read-only list of timed metadata tracks. */
declare class MediaPlaybackTimedMetadataTrackList extends Array {
    /** Returns an iterator that iterates over the items in the collection. */
    first(): Windows.Foundation.Collections.IIterator;
    /** Returns the timed metadata track at the specified index. */
    getAt(index: number): Windows.Media.Core.TimedMetadataTrack;
    /** Retrieves the timed metadata tracks that start at the specified index in the list. */
    getMany(startIndex: number): { /** The timed metadata tracks that start at startIndex in the list. */ items: Windows.Media.Core.TimedMetadataTrack; /** Retrieves the timed metadata tracks that start at the specified index in the list. */ returnValue: number; };
    /** Gets the presentation mode of the timed metadata track with the specified index. */
    getPresentationMode(index: number): Windows.Media.Playback.TimedMetadataTrackPresentationMode;
    /** Retrieves the index of a specified timed metadata track in the list. */
    indexOf(value: Windows.Media.Core.TimedMetadataTrack): { /** If the timed metadata track is found, this is the zero-based index of the audio track; otherwise, this parameter is 0. */ index: number; /** True if the timed metadata track is found; otherwise, false. */ returnValue: boolean; };
    /** Occurs when the presentation mode of the MediaPlaybackTimedMetadataTrackList changes. */
    onpresentationmodechanged: (ev: Windows.Foundation.TypedEventHandler) => any;
    addEventListener(type: "presentationmodechanged", listener: (ev: Windows.Foundation.TypedEventHandler) => any): void;
    removeEventListener(type: "presentationmodechanged", listener: (ev: Windows.Foundation.TypedEventHandler) => any): void;
    /** Sets the presentation mode of the timed metadata track with the specified index. */
    setPresentationMode(index: number, value: Windows.Media.Playback.TimedMetadataTrackPresentationMode): void;
    /** Gets the number of timed metadata tracks in the list. */
    size: number;
    addEventListener(type: string, listener: EventListenerOrEventListenerObject): void;
    removeEventListener(type: string, listener: EventListenerOrEventListenerObject): void;
}

This is the current type definition generated by script. This class has Array in its prototype chain and it have its own indexOf method whose signature conflicts with Array.indexOf. This confliction makes the compiler keep complaining and I need to make it silent. Is there a known way to make this work?

A solution here have to indicate that the class inherits from Array.

Note: I cannot modify the semantics as this is one of the current UWP APIs.

2 Answers 2

2

You'll need to include the same signatures from the original implementation, so start off with

declare class MediaPlaybackTimedMetadataTrackList extends Array {
    indexOf(value: any): { index: number; returnValue: boolean; };
    indexOf(searchElement: any, fromIndex?: number): number;
}

But clearly that's problematic because anything that feeds in a fromIndex is not going to get number if the implementation doesn't respect Array's original behavior.

So what you can instead do is:

declare class MediaPlaybackTimedMetadataTrackList extends Array {
    indexOf(value: any): { index: number; returnValue: boolean; };
    indexOf(value: any, ...extra: any[]): { index: number; returnValue: boolean; };
    indexOf(searchElement: any, fromIndex?: number): number;
}

It's a bit of a hack, but you can now no longer get the original implementation because a caller will always resolve to the second overload.

If you want to try to avoid calling the second overload, you can also make it return void.

declare class MediaPlaybackTimedMetadataTrackList extends Array {
    indexOf(value: any): { index: number; returnValue: boolean; };
    indexOf(value: any, ...extra: any[]): void;
    indexOf(searchElement: any, fromIndex?: number): number;
}

or { "This type should never be used, stop what you're doing": void }

Sign up to request clarification or add additional context in comments.

1 Comment

Alternatively you could make the return type never instead of void to make it a compile-time error that will bring attention to the erroneous usage.
1

The key to sustainable OOP is to follow the Liskov substitution principle. So the derived Array should still be the Array. So, we should let the original indexOf definition in place with overload:

declare class MediaPlaybackTimedMetadataTrackList extends Array {
    ...
    indexOf(searchElement: Windows.Media.Core.TimedMetadataTrack, fromIndex?: number)
       : number;
    indexOf(value: Windows.Media.Core.TimedMetadataTrack)
       : { index: number; returnValue: boolean; };
}

3 Comments

It satisfies TS compiler but then the signatures become wrong as indexOf(track, 0) returns an object rather than a number value.
Liskov principle should be the answer. Do not change the shape of the object. That would be my advise. If you derive, do keep the parent shape in place. If any polymorphic operation will expect Array, it will expect the indexOf will return a number. I do not know how to express that more.. hope it helps a bit at least
The class is from the existing Universal Windows Platform so I cannot fix the shape.

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.