Reputation: 189
I'm using Typescript with React and struggling to get a type correct.. What I am trying to achieve is that for the interface Car the property colorId is required if carColor is 'blue' otherwise it should not be included. Any feedback on how to achieve this?
interface Car {
carBrand: string;
carColor: 'black' | 'blue';
colorId?: string;
}
Upvotes: 0
Views: 50
Reputation: 8168
You can use generics and Omit
.
Create a BaseCar
interface that has carBrand
, carColor
and carId
properties and then create a Car
type that conditionally decides the colorId
property.
interface BaseCar {
carBrand: string;
carColor: "black" | "blue";
colorId: string;
}
type Car<T> = T extends "black" ? Omit<BaseCar, "colorId"> : BaseCar;
const blueCar: Car<"blue"> = {
carBrand: "tesla",
carColor: "blue",
colorId: "123",
};
const blackCar: Car<"black"> = {
carBrand: "honda",
carColor: "black",
};
// @ts-expect-error
const blueCarWithoutId: Car<"blue"> = {
carBrand: "tesla",
carColor: "blue",
};
const blackCarWithId: Car<"black"> = {
carBrand: "honda",
carColor: "black",
// @ts-expect-error
colorId: "123",
};
Upvotes: 3
Reputation: 11558
type CarColors = "black" | "blue";
// create generic that passed color as asgument
interface Car<C extends CarColors = "black"> {
carBrand: string;
carColor: C;
colorId: string;
}
// create conditional type that omits carColor when color is black
type ColoredCar<C extends CarColors = "black"> = C extends "blue" ? Car<"blue"> : Omit<Car, "carColor">;
// use agrument blue to require color
const myCar: ColoredCar<"blue"> = {
carBrand: "bmw",
carColor: "blue",
colorId: "123"
};
// otherwise it is omitted
const myCar2: ColoredCar = {
carBrand: "bmw",
colorId: "123"
};
Upvotes: 2