Open Meess opened 1 year ago
I ran into this, and I am left with the assumption that there's reasoning behind that typing. Here is a workaround that will make it easier for you.
For each kind of even you'd like to check for, create a function that will
typing the event directly as one of the specific MidiEvents types avoids the IValue issue for some reason.
EX:
import {
TMidiEvent,
IMidiNoteOnEvent,
IMidiNoteOffEvent,
} from "midi-json-parser-worker";
type EventKeysToCheck = "noteOn" | "noteOff";
function typedMidiEvent(
eventKeyToCheck: "noteOn",
event: TMidiEvent,
): IMidiNoteOnEvent | null;
function typedMidiEvent(
eventKeyToCheck: "noteOff",
event: TMidiEvent,
): IMidiNoteOffEvent | null;
function typedMidiEvent(eventKeyToCheck: EventKeysToCheck, event: TMidiEvent) {
if (eventKeyToCheck in event) {
return event;
}
return null;
}
Then ts should work normally:
Short version:
Long version:
To take one event as example: IMidiSetTempoEvent
IMidiSetTempoEvent
eventually extendsTValue
which can be a lot (see extending type chain below). This make it extremely hard to determine which event we're looking when have file of typeIMidiFile
.For example I have a function that takea a IMidiFile as input first the type
IMidiFile
needs to be derived as it's not exported , i.e.:IMidiFile
contains the tracks, typed as Tracks[][], the Tracks Type itself is not exported hence should also be derived, but is a bit more complex:Now we can Tracks an input type for a function in our own codebase. If we create a loop over the events in a track, it's difficult to get the typing right for that event. It might be possible to do the following:
But that will give a type error, because the type where 'setTempo' exists on is
IMidiSetTempoEvent
, which extends IMidiMetaEvent, which extendsIValueMap
which have string keys andTValue
as value. See the following chain:which basically means
IMidiSetTempoEvent
can have any key, and can have any value of TValue. So with our check'setTempo' in Event
TypeScript can't simplify the type because 'setTempo' is both a valid key forIMidiSetTempoEvent
andIValueMap
(because it fits the key type string).So accessing
Event.setTempo.microsecondsPerQuarter
will give an error because setTempo can also be a TValue, and TValue doesn't specify an object so it will error saying it can't accessmicrosecondsPerQuarter
, i.e. the error:This makes it very difficult to properly check for an event and have the proper typing of the event to handle it, because basically every event becomes a big IValueMap which can be almost anything (except for an object).