Home > other >  Typescript type inference with mapped type and enums in a function why not works?
Typescript type inference with mapped type and enums in a function why not works?

Time:03-14

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'
});


WYSIWYG => WHAT YOU SHOW IS WHAT YOU GET

  • Related