You can't represent Palette as a single non-generic interface, but you can make it a union of each desired pairing of colorType and color:
type Palette = {
colorType: "light";
color: "EC3333" | "E91515";
} | {
colorType: "dark";
color: "#100F0F" | "140F0F";
}
You can even make the compiler compute this for you from Colors by mapping over the keys of Colors and then immediately indexing into the resultant mapped object type:
type Palette = { [K in keyof Colors]: {
colorType: K
color: Colors[K]
} }[keyof Colors];
You can verfiy via IntelliSense that this results in the same type as before, with the advantage that it will automatically update if you change Colors.
Armed with this union type, you can start using Palette and seeing the constraint enforced and understood:
const badPalette: Palette = {
colorType: "dark",
color: "E91515"
} // error!
const goodPalette: Palette = {
colorType: "dark",
color: "140F0F"
} // okay
Playground link to code