I can't figure out, why doesn't work the type inference here (see below in the code).
enum Vehicle {
Car,
Bus,
Plane,
}
interface CarParams {
carId: string;
}
interface BusParams {
busId: string;
}
interface PlaneParams {
planeId: string;
}
type Params = {
[Vehicle.Bus]: BusParams;
[Vehicle.Car]: CarParams;
[Vehicle.Plane]: PlaneParams;
};
function showDriver<T extends Vehicle>(vehicle: T, params: Params[T] ): void {
// ...
if (vehicle === Vehicle.Bus) {
params.busId //<---- Property 'busId' does not exist on type 'CarParams | BusParams | PlaneParams'.
// Type inference doesn't work here!
}
}
showDriver(Vehicle.Bus, { busId: '' }) // <--- type inference works here!
CodePudding user response:
There is an in
operator narrowing
available, and we can take advantage of that to identify a particular member type in the union.
enum Vehicle {
Car,
Bus,
Plane,
}
interface CarParams {
carId: string;
}
interface BusParams {
busId: string;
}
interface PlaneParams {
planeId: string;
}
type Params = {
[Vehicle.Bus]: BusParams;
[Vehicle.Car]: CarParams;
[Vehicle.Plane]: PlaneParams;
};
function showDriver<T extends Vehicle>(vehicle: T, params: Params[T]): void {
// ...
if ("busId" in params) {
console.log(params.busId);
}
if ("carId" in params) {
console.log(params.carId);
}
if ("planeId" in params) {
console.log(params.planeId);
}
}
showDriver(Vehicle.Bus, { busId: 'bus123' });
showDriver(Vehicle.Car, { carId: 'car123' });
showDriver(Vehicle.Plane, { planeId: 'plane123' });
Illustration
"use strict";
var Vehicle;
(function(Vehicle) {
Vehicle[Vehicle["Car"] = 0] = "Car";
Vehicle[Vehicle["Bus"] = 1] = "Bus";
Vehicle[Vehicle["Plane"] = 2] = "Plane";
})(Vehicle || (Vehicle = {}));
function showDriver(vehicle, params) {
// ...
if ("busId" in params) {
console.log(params.busId);
}
if ("carId" in params) {
console.log(params.carId);
}
if ("planeId" in params) {
console.log(params.planeId);
}
}
showDriver(Vehicle.Bus, {
busId: 'bus123'
});
showDriver(Vehicle.Car, {
carId: 'car123'
});
showDriver(Vehicle.Plane, {
planeId: 'plane123'
});