简体   繁体   English

类型检查联合类型

[英]Type checking union types

Consider the following code:考虑以下代码:

interface CarData{
   wheels: number
}

interface PlaneData{
   wings: number
}

interface Vehicle{
   type: string,
   data: CarData | PlaneData
}

function printWheels(data: CarData){
   console.log("Number of wheels: " + data.wheels);
}

function printWings(data: PlaneData){
   console.log("Number of wings: " + data.wings);
}

let vehicle: Vehicle;

switch (vehicle.type)
{
    case "car":
        printWheels(vehicle.data);
        break;
    case "plane":
        printWings(vehicle.data);
        break;
}

I get the error Argument of type 'CarData | PlaneData' is not assignable to parameter of type 'CarData'. Property 'wheels' is missing in type 'PlaneData' but required in type 'CarData'.我收到Argument of type 'CarData | PlaneData' is not assignable to parameter of type 'CarData'. Property 'wheels' is missing in type 'PlaneData' but required in type 'CarData'. Argument of type 'CarData | PlaneData' is not assignable to parameter of type 'CarData'. Property 'wheels' is missing in type 'PlaneData' but required in type 'CarData'. which makes sense since it doesn't know what type data is.这是有道理的,因为它不知道数据是什么类型。 It can be solved by adding a shared member that tells the type.可以通过添加一个告诉类型的共享成员来解决。 The following code type checks correctly:以下代码类型检查正确:

interface CarData
{
    kind: "carData",
    wheels: number
}

interface PlaneData
{
    kind: "planeData",
    wings: number
}

interface Vehicle
{
    type: string,
    data: CarData | PlaneData
}

function printWheels(data: CarData)
{
    console.log("Number of wheels: " + data.wheels);
}

function printWings(data: PlaneData)
{
    console.log("Number of wings: " + data.wings);
}

let vehicle: Vehicle;

switch (vehicle.type)
{
    case "car":
        if (vehicle.data.kind == "carData") printWheels(vehicle.data);
        break;
    case "plane":
        if (vehicle.data.kind == "planeData") printWings(vehicle.data);
        break;
}

But this gives me extra values in data interfaces which I don't like.但这给了我不喜欢的数据接口中的额外价值。 Is there a more elegant way to do this?有没有更优雅的方法来做到这一点?

You can do a switch directly on the discriminating field and TS will be able to work out that you are calling each function safely您可以直接在鉴别字段上进行切换,TS 将能够确定您正在安全地调用每个 function

switch (vehicle.data.kind) {
    case "carData":
        // vehicle.data is of type CarData
        printWheels(vehicle.data);
        break;
    case "planeData":
        // vehicle.data is of type PlaneData
        printWings(vehicle.data);
        break;
}

See this TypeScript Playground to see how this works without type errors请参阅此 TypeScript Playground以了解其如何在没有类型错误的情况下工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM