学习TypeScript - 投射类型 [英] Learning TypeScript - Casting Types

查看:85
本文介绍了学习TypeScript - 投射类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是TypeScript的新手,我正在玩各种语言功能。下面是我在其中一个在线课程中一直在研究的代码示例。

I'm new to TypeScript and I'm playing around with the various language features. Below is a code sample I've been working on during one of the many online courses.

我遇到了继承和重载工作正常的问题。在整个代码中
我使用的是一辆基本型Auto汽车,以及一辆非儿童级卡车的卡车。

I'm having issues getting inheritence and overloading to work properly. throughout the code I make use of a car which is of base class Auto, and a truck which is off child class Truck.

我正在尝试看看是否可以将汽车作为卡车投入并访问专用功能HonkHorn。
此外,我正在尝试将卡车投回到Auto并访问WriteDetails的基本函数。

I'm trying to see if it is possible to cast the car as a Truck and access the specialized function HonkHorn. Also I'm trying to cast a truck back to an Auto and access the base function for WriteDetails.

在这两种情况下,似乎对象保持不变原始类型。所以typecast4.HonkHorn();生成运行时错误:未捕获TypeError:typecast4.HonkHorn不是函数。

In both cases it seems the objects stay of their original type. So typecast4.HonkHorn(); generates a runtime error: Uncaught TypeError: typecast4.HonkHorn is not a function.

尝试将Truck转换为Auto将始终导致调用WriteDetails的专用覆盖。铸造代码一直在样本底部。

Trying to cast back Truck to Auto will always result in the specialized override for WriteDetails to be called. The casting code is all the way at the bottom of the sample.

有人可以帮我理解为什么会发生这种情况吗?

Can someone please help me understand why this is happening?

提前致谢!

// defines the structure of auto options
interface IAutoOptions{
    engine: Engine,
    color: string,
    price: number,
    year: number
}

// extends autooptions with truck specific options
interface ITruckOptions extends IAutoOptions{
    fourbyfour: boolean,
    bedlength: string
}

// defines the structure of engines
interface IEngine {
    enginetype: string;
    horsepower: number;
    hydraulicpump?: string
    start(warmuptime: number, callback: () => void): void;
    stop(): void;
}

// the engine class must implement the members as specified in the IEngine interface
class Engine implements IEngine{
    enginetype: string;
    horsepower: number;
    hydraulicpump?: string; //optional hydraulic parameter
    constructor(enginetype: string, horsepower: number, hydraulicpump? : string ) {
        this.enginetype = enginetype;
        this.horsepower = horsepower;
        if (!(hydraulicpump)){
            hydraulicpump = "Not Available"; //if no hydraulic parameter is provided we set it to "Not Available"
        }
        this.hydraulicpump = hydraulicpump;
    }
    // start requires a callback parameter which accepts a specialized callback object/function that accepts and returns nothing
    // by accepting a callback object/function that code can be seperated off, which makes this class much cleaner and organized
    start(warmuptime: number, callback: () => void) { 
        window.setTimeout(() => {
            callback();
            document.write(this.enginetype + " has started!" + "</br>");
        }, warmuptime);
    };
    stop() { 
        document.write(this.enginetype + " has stopped!" + "</br>");
    };
}

// base class for autos
class Auto {
    engine: Engine;
    color: string;
    price: number;
    year: number;

    constructor(options: IAutoOptions) {
        this.engine = options.engine;
        this.color = options.color;
        this.price = options.price;
        this.year = options.year;
    }

    //WriteDetails contains the base details for each Auto which can be overriden in specialized classes
    WriteDetails() {
        document.write("Color: " + this.color + "</br>");
        document.write("Year: " + this.year + "</br>");
        document.write("Price: $"  + this.price + "</br>");
        document.write("Engine Type: " + this.engine.enginetype + "</br>");
        document.write("Horse Power: " + this.engine.horsepower + "</br>");
        document.write("Hydraulic Pump: " + this.engine.hydraulicpump + "</br>");    
    };
}

// Truck extends Auto to add Truck specific fields and function overloads
// Note that it does not contains all the base fields from Auto thus making it much smaller and cleaner
// Only truck specific code is added.
class Truck extends Auto{
    fourbyfour: boolean;
    bedlength: string;
    constructor(options: ITruckOptions) {
        // to overload the constructor super() must to be called, which calls the base class constructor in Auto
        super(options);
        this.bedlength = options.bedlength;
        this.fourbyfour = options.fourbyfour;
    }
    // WriteDetails overrides the Auto WriteDetails, but first calls the base WriteDetails function
    WriteDetails() {
        super.WriteDetails();
        document.write("Bed Length: " + this.bedlength + "</br>");
        document.write("4x4 : " + this.fourbyfour + "</br>");
    };

    HonkHorn() {
        document.write("Honk Honk!</br>");
    }
}

// below is one of the notations to define a callback object that can be used to call
// the start function on the Engine class
// this callback function has encapsulated car specific logic for starting the engine
// much cleaner than putting the specialized code in the Auto class

var CarEngineStart = () => {
    document.write("<h1>Starting Car</h1>");
    document.write("Check Tires!" + "</br>");
    document.write("Fasten Seatbelts!" + "</br>");
    document.write("Check Mirrors!" + "</br>");
    document.write("Starting Engine!" + "</br>");
};

// yet another way to define a callback object (function)
// this callback function has encapsulated truck specific logic for starting the engine
// much cleaner than putting the specialized code in the Auto or Truck classes

function TruckEngineStart() {
    document.write("<h1>Starting Truck</h1>");
    document.write("Check Tires!" + "</br>");
    document.write("Check if load is properly fastened!" + "</br>");
    document.write("Check timesheet!" + "</br>");
    document.write("Fasten Seatbelts!" + "</br>");
    document.write("Check Mirrors!" + "</br>");
    document.write("Starting Engine!" + "</br>");
}

// ###################### Start logic

// creating an engine
var carengine = new Engine("V8", 300);
// creating another engine, but now providing the optional hydraulicpump parameter
var truckengine = new Engine("V12", 1000, "Flexpump 3000");

var car = new Auto({
    engine: carengine,
    color: 'Blue',
    price: 20000,
    year: 2017
});

var truck = new Truck({
    engine: truckengine,
    color: 'Red',
    price: 80000,
    year: 2015,
    bedlength: 'Long Bed',
    fourbyfour: true
});
document.write("<h1>Car Details</h1>");
car.WriteDetails();

document.write("<h1>Truck Details</h1>");
truck.WriteDetails();

truck.engine.start(10000, TruckEngineStart);
car.engine.start(5000, CarEngineStart);

window.setTimeout(() => {
    document.write("<h1>Stopping Car</h1>");
    car.engine.stop();
    document.write("<h1>Stopping Truck</h1>");
    truck.engine.stop();
}, 15000);

document.write("<h1>Casting Autos</h1>");
document.write("<h2>Auto WriteDetails for Car</h2>");
var typecast: Auto;
typecast = car;
typecast.WriteDetails();
document.write("<h2>Truck WriteDetails for Car with type cast</h2>");
var typecast4: Truck;
typecast4 = <Truck>car;
typecast4.HonkHorn();
typecast4.WriteDetails();
document.write("<h2>Auto WriteDetails for Truck without type cast</h2>");
var typecast2: Auto;
typecast2 = truck;
typecast2.WriteDetails();
document.write("<h2>Auto WriteDetails for Truck with type cast</h2>");
var typecast3: Auto;
typecast3 = <Auto>truck;
typecast3.WriteDetails();


推荐答案

在Typescript中没有类型转换,但只有类型断言。这用于类型检查,它不会影响运行时行为。

There is no type casting in Typescript, but only type assertions. This is for type checking and it won't influence runtime behavior.

例如,类型断言:

car as Truck  // older syntax syntax: <Truck> car 

告诉编译器 car 是类型 Truck ,但它不会影响生成的JS代码。

tells the compiler that the car is of type Truck, but it won't influence the generated JS code.


TypeScript允许您以任何方式覆盖其推断和分析的类型视图。这是通过一种称为类型断言的机制完成的。 TypeScript的类型断言纯粹是告诉编译器你比它更了解类型,并且它不应该猜测你。

TypeScript allows you to override its inferred and analyzed view of types in any way you want to. This is done by a mechanism called "type assertion". TypeScript's type assertion is purely you telling the compiler that you know about the types better than it does, and that it should not second guess you.

类型断言与强制转换

它之所以不被称为类型转换,是因为转换通常意味着某种运行时支持。但是,类型断言纯粹是一个编译时构造,也是一种为编译器提供关于如何分析代码的提示的方法。

The reason why it's not called "type casting" is that casting generally implies some sort of runtime support. However type assertions are purely a compile time construct and a way for you to provide hints to the compiler on how you want your code to be analyzed.

https://basarat.gitbooks.io/typescript /content/docs/types/type-assertion.html

这篇关于学习TypeScript - 投射类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆