Is there a way in TypeScript to create a nested version of a Flags
type mentioned in Advanced types documentation?
This works well:
type Flags<T> = {
[P in keyof T]: boolean;
}
interface Colors {
red: string;
green: string;
blue: string;
}
const activeColors: Flags<Colors> = {
red: true,
green: true,
blue: false
}
But what if I wanted to create let's say a NestedFlags
type that would be able to handle nested objects like this?
interface NestedColors {
red: string;
green: string;
blue: string;
more: {
yellow: string;
violet: string;
black: string;
}
}
const activeNestedColors: NestedFlags<NestedColors> {
red: true,
blue: false,
green: true,
more: {
yellow: false,
violet: true,
black: true
}
}
I am able to create a NestedFlags
type with [P in keyof T]: boolean | NestedFlags<T[P]>
. That solution works well except the fact that it allows me to create an object with eg. more: false
which is undesirable in my case.
Thank you!
You probably want mapped conditional types, which will be available starting in TypeScript v2.8, to be released sometime this month (March 2018). You can use it now with typescript@next
. Here's a first shot at how I'd implement it:
type NestedFlags<T> = {
[K in keyof T]: T[K] extends object ? NestedFlags<T[K]> : boolean
}
The above line uses the conditional types ternary type syntax. It means: for every key in T
, the property type for NestedFlags<T>
will depend on whether the original property is an object type or not. If the original property is not an object type, the corresponding property will be boolean. If the original property is an object type, then the corresponding property will be a NestedFlags<>
applied to that object type.
This gives you the following behavior:
interface NestedColors {
red: string;
green: string;
blue: string;
more: {
yellow: string;
violet: string;
black: string;
}
}
// okay
const activeNestedColors: NestedFlags<NestedColors> = {
red: true,
blue: false,
green: true,
more: {
yellow: false,
violet: true,
black: true
}
}
// error
const badActiveNestedColors: NestedFlags<NestedColors> = {
red: true,
blue: false,
green: true,
more: false
}
// Types of property 'more' are incompatible.
// Type 'boolean' is not assignable to ...
TypeScript complains about badActiveNestedColors
, saying that more
should not be a boolean
.
Hope that helps. Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With