Типы проверки типа объединения - PullRequest
0 голосов
/ 21 апреля 2020

Рассмотрим следующий код:

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

Я получаю ошибку 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'., которая имеет смысл, поскольку не знает, что это за тип данных. Это может быть решено добавлением общего члена, который сообщает тип. Следующий тип кода проверяет правильно:

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

Но это дает мне дополнительные значения в интерфейсах данных, которые мне не нравятся. Есть ли более элегантный способ сделать это?

1 Ответ

0 голосов
/ 21 апреля 2020

Вы можете переключиться непосредственно в поле различения, и TS сможет определить, что вы вызываете каждую функцию безопасно

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

См. эту площадку TypeScript , чтобы увидеть, как это работает без ошибок типа

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...