Let's say I have these type definitions:
export type Event = {
name: EventName,
timestamp: Timestamp,
};
export type EventWithMetadata = Event & {
deviceId: ID,
};
I want to create a common function interface like this:
export type SideEffect = (event: Event, run?: Run) => Partial<Run>;
and utilize it with the following function
// Please note that there are many similar side-effect functions available, each working with different variations of the Event type. This is just one example.
const updateTiming: SideEffect = (event: EventWithMetadata, run) => {
log.debug('updateTiming: %j', event);
return {
lastUpdated: event.timestamp,
deviceId: event.deviceId,
};
};
However, I encounter this error:
error TS2322: Type '(event: EventWithMetadata, run: Run | undefined) => { startTime: number; deviceId: string; }' is not assignable to type 'SideEffect'.
Types of parameters 'event' and 'event' are incompatible.
Type 'Event' is not assignable to type 'EventWithMetadata'.
Property 'deviceId' is missing in type 'Event' but required in type '{ deviceId: string; }'.
This error makes sense as TypeScript assumes I am trying to convert an Event
into an EventWithMetadata
, which is not possible.
After exploring various options such as generics, overloads, and union types, the most suitable solution I found is described in this post. However, I am not fond of the outcome and do not wish to adopt it as a standard practice:
const updateTiming: SideEffect = (inputEvent: Event, run) => {
const event = inputEvent as EventWithMetadata; // <- This workaround is not ideal.
log.debug('updateTiming: %j', event);
return {
lastUpdated: event.timestamp,
deviceId: event.deviceId,
};
};
Is there a better approach than using casting?