函数中具有映射类型和枚举的Typescript类型推理为什么不起作用



我不明白,为什么不在这里进行类型推断(请参阅下面的代码(。

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!

有一个inoperator narrowing可用,我们可以利用它来识别联合中的特定成员类型。

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

插图

"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

不完全确定为什么它不起作用,但我相信这可能是因为Params类型不是JS对象,TS不支持这样的映射类型。我发现了它的其他微妙的局限性,不幸的是,这些局限性让我重新构建了代码。TS非常强大,但它仍在开发中且不完整。

在任何情况下,我采取了一种稍微不同的方法,这里似乎可以按照您的意图工作,并允许您直接与枚举进行比较,而不必使用每种类型唯一的字段。

enum Vehicle {
Car,
Bus,
Plane
}
interface CarParams {
kind: Vehicle.Car;
carId: string;
}
interface BusParams {
kind: Vehicle.Bus;
busId: string;
}
interface PlaneParams {
kind: Vehicle.Plane;
planeId: string;
}
type Params = CarParams | BusParams | PlaneParams;
function showDriver(params: Params): void {
// ...
if (params.kind === Vehicle.Bus) {
params.busId = "1"; // exists
params.planeId = "2"; // does not exist
}
}
showDriver({
kind: Vehicle.Bus,
busId: "", // exists
planeId: "" // does not exist
});

最新更新