函数中映射类型和枚举的 Typescript 类型推断为什么不起作用?
Typescript type inference with mapped type and enums in a function why not works?
我想不通,为什么这里的类型推断不起作用(见下面的代码)。
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!
有 in
operator 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
});
我想不通,为什么这里的类型推断不起作用(见下面的代码)。
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!
有 in
operator 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
});