TypeScript接口向下转换

Dun*_*Luk 4 javascript types casting typescript

我有一个接口正在扩展另一个接口。现在,我试图将超接口类型的变量放入需要子接口类型参数的函数中。这是不可能的,因为超级接口类型变量缺少某些属性。

有点难以解释,所以我创建了一个带有Animal接口的示例,该示例由Horse接口扩展:

interface Animal {
    age:number;
    //... 100 other things
}

interface Horse extends Animal {
    speed:number;
}
Run Code Online (Sandbox Code Playgroud)

现在,我有了一个带有一个私有函数(rideHorse)的模块,该函数仅接受一个Horseas参数。还有一个公共函数(rideAnimal),它接受所有,Animal如下所示:

module AnimalModule {
    function rideHorse(horse:Horse) {
        alert(horse.speed);
    }

    export function rideAnimal(animal:Animal) {
        animal.speed = 10; // Error: Animal cannot have speed
        rideHorse(animal); // Error: 'animal' needs speed
    }
}

// Calling the rideAnimal function
var myAnimal:Animal = {
    age: 10
};
AnimalModule.rideAnimal(myAnimal);
Run Code Online (Sandbox Code Playgroud)

如您所见,这是行不通的,因为的animal参数rideAnimal没有speed。所以我的问题是:如何将我animal转换为a HorsespeedrideAnimal函数内部手动添加,这样错误会消失?

Ale*_*lex 5

是的,您可以使用用户定义的类型防护来处理这种自定义类型评估:

interface Animal
{
    age: number;
    //... 100 other things
}

interface Horse extends Animal
{
    speed: number;
}

module AnimalModule
{
    function rideHorse(horse: Horse)
    {
        alert(horse.speed);
    }

    function isHorse(a: Animal): a is Horse
    {
        return "speed" in a;
    }

    export function rideAnimal(animal: Animal)
    {
        if (isHorse(animal))
        {
            animal.speed = 10; // Ok
            rideHorse(animal); // Ok
        } else
            throw new Error("You can only ride horses")
    }
}
Run Code Online (Sandbox Code Playgroud)

如果HorseAnimal是类,您可以直接完成if (animal instanceof Horse)而不是使用自定义类型保护isHorse


Val*_*éry 5

您可以将自己Animal变成Horse这样。

function rideAnimal(animal:Animal) {
    var horse = animal as Horse;
    horse.speed = 10;
    rideHorse(horse);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您想要更安全,请使用转换函数 `toHorse`,它接受一个 `Animal`,将其转换为一个 `Horse`,并在添加一个 `speed` 后返回它。 (2认同)