0

I have these types:

interface Color {
  color: string
}

type DarkerColor<T> = T & Color & { darker: string }

type ColorInfo<T> = DarkerColor<T> & {
  hue: number
  luminance: number
  opacity?: number
}

and these functions:

function computeDarkerColor<T extends Color>(dataset: T[]): Array<DarkerColor<T>> {...}
function computeHueAndLuminance<T extends Color>(value: Array<DarkerColor<T>>): Array<ColorInfo<T>> {...}
function computeOpacity<T extends Color>(value: Array<ColorInfo<T>>): Array<Required<ColorInfo<T>>> {...}

So, basically, computeHueAndLuminance gets in input an object (array of objects) and returns another object (array of objects) that contanins the proprerties hue and luminance. The function computeOpacity gets in input that object (array of objects) and returns the same objects (array of objects) with also the opacity property.

To do that I thought to use a single type ColorInfo with hue and luminance mandatory and opacity optional. Then use Required but it seems not to work. I tried also Partial in that way:

interface Color {
  color: string
}

type DarkerColor<T> = T & Color & { darker: string }

type ColorInfo<T> = DarkerColor<T> & {
  hue: number
  luminance: number
  opacity: number
}


function computeDarkerColor<T extends Color>(dataset: T[]): Array<DarkerColor<T>> {...}
function computeHueAndLuminance<T extends Color>(value: Array<DarkerColor<T>>): Array<Partial<ColorInfo<T>>> {...}
function computeOpacity<T extends Color>(value: Array<ColorInfo<T>>): Array<ColorInfo<T>> {...}

but I get the same error:

Type 'T & Color & { darker: string; } & { hue: number; luminance: number; opacity: number; }' is not assignable to type 'Required<ColorInfo<T>>'.

What is the problem?

whitecircle
  • 237
  • 9
  • 34

1 Answers1

1

As discussed in could be instantiated with a different subtype of constraint 'object'

you cannot modify the generic extended type. One possible solution is to make the partial outside of the extended type. In case you need a partial type that would work.

interface Color {
  color: string
}

type DarkerColor<T> = T & Color & { darker: string }

type ColorInfo<T> = DarkerColor<T> & Partial<{
  hue: number
  luminance: number
  opacity: number
}>


function computeDarkerColor<T extends Color>(dataset: T[]): Array<DarkerColor<T>> {...}
function computeHueAndLuminance<T extends Color>(value: Array<DarkerColor<T>>): Array<ColorInfo<T>> {...}
function computeOpacity<T extends Color>(value: Array<ColorInfo<T>>): Array<ColorInfo<T>> {...}

However to solve the issue of the 2 almost identical types you can use optional types or composition of any type for example Omit.

OMIT:

interface Color {
  color: string
}

type DarkerColor<T> = T & Color & { darker: string }

type ColorInfo<T> = DarkerColor<T> & {
  hue: number
  luminance: number
  opacity: number
}


function computeDarkerColor<T extends Color>(dataset: T[]): Array<DarkerColor<T>> {...}
function computeHueAndLuminance<T extends Color>(value: Array<DarkerColor<T>>): Array<Omit<ColorInfo<T>, 'opacity'>> {...}
function computeOpacity<T extends Color>(value: Array<ColorInfo<T>>): Array<ColorInfo<T>> {...}
Antoine Eskaros
  • 836
  • 5
  • 22
  • Thank you Antoine but doing in that way I can't distinguish between the type that has `opacity` and the one that hasn't `opacity`, right? – whitecircle Aug 16 '20 at 15:51