I'm trying to define property type based on generic type.
interface Option<T> {
text: string
value: T
}
class MultiSelect<T, TGroup extends boolean = false> {
public groups: TGroup;
public options: TGroup extends true ? { group: Option<T> } : Option<T>
constructor(groups: TGroup, options: TGroup extends true ? { group: Option<T> } : Option<T>) {
this.groups = groups
this.options = options
}
public get allOptions(): Option<T> {
return this.groups ? this.options.group : this.options
}
}
But this.options
is not being discriminated by TGroup
and instead becomes a union Option<T> | { group: Option<T>; }
Therefore when trying to access this.optoin.group from within ternary it errors
Property 'group' does not exist on type 'Option<T> | { group: Option<T>; }'.
Property 'group' does not exist on type 'Option<T>'
Here is Typescript Playground
CodePudding user response:
Typescript type discrimination requires that the types that you want to discriminate between be defined in a union. You can have TS discriminate here if you combine the groups
and options
properties into a single type and then create a union of the two variations.
interface Option<T> {
text: string
value: T
}
type SelectOptions<T> = {
groups: false
options: Option<T>
} | {
groups: true
options: {
group: Option<T>
}
}
class MultiSelect<T> {
private selectOptions: SelectOptions<T>
constructor(selectOptions: SelectOptions<T>) {
this.selectOptions = selectOptions
}
public get allOptions(): Option<T> {
return this.selectOptions.groups ? this.selectOptions.options.group : this.selectOptions.options
}
}