0

I have a base Type that is extended upon by two interfaces. I then have another interface which is a Union of the two Types.

Later on I process these type to replace the Number date property which an actual Date object, so I have a type for that too.

However, upon trying to read the lens property in my component (after a condition I thought should differentiate it as a Camera, I get an error.

Property 'lens' does not exist on type 'DatedDevice'.

export enum DeviceType {
  Camera = 'camera-device',
  Phone = 'phone-device'
}

interface DeviceBase {
  id: string;
  date: number;
}

export interface Camera extends DeviceBase {
  lens: string;
  type: DeviceType.Camera;
}

export interface Phone extends DeviceBase {
  receiver: string;
  type: DeviceType.Phone;
}

// Union of two extended interfaces
export type Device = Camera | Phone;

// Type for replacing number with Date
export interface DatedDevice extends Omit<Device, 'date'> {
  date: Date;
}

// Error in component.
// 'device' is a prop of type 'DatedDevice'
if (device.type === DeviceType.Text) {
  console.log(device.lens);
  // ^ Property 'lens' does not exist on type 'DatedDevice'

}
cjhines
  • 1,148
  • 3
  • 16
  • 32

1 Answers1

1

Based on this answer, you need to use distributive conditional types

Unfortunately I can't add an in depth explanation of the solution other than that your Omit doesn't work like you expect

type DistributiveOmit<T, K extends keyof any> = T extends any
  ? Omit<T, K>
  : never;
  
export type DatedDevice = DistributiveOmit<Device, 'date'> & {
  date: Date;
}

if (device.type === DeviceType.Camera) {
  console.log(device.lens);
} else {
  console.log(device.receiver)
}
Asaf Aviv
  • 11,279
  • 1
  • 28
  • 45