我对打字稿中的投射有疑问。
我有一个用例,将一个对象强制转换为具有方法的类的特定类型。之后,当我想调用此方法时,它是未定义的,请比较下面的代码段:
export class Test {
property1: any;
property2: any;
constructor(){}
sayHello(): string {
return 'hello';
}
}
testData = {
property1: '',
property2: 2
} as Test;
testData.sayHello(); <-- undefined
我还在stackblitz上的一个有角度的应用程序中准备了一个工作示例,或者不是工作示例:https://stackblitz.com/edit/angular-y3s9r4
有人可以解释这种行为吗?还有inherit
方法怎么可能?
答案 0 :(得分:6)
在打字稿中,这称为类型断言,而不是强制类型转换。术语不同的原因恰恰是它的行为与其他语言不同,即没有运行时行为。类型断言不会转换值并且不会执行任何运行时检查,它们只会告诉编译器您(作为开发人员)知道某个值将属于某种类型。如何掌握这些知识与编译器无关。
因此,此代码:
testData = {
property1: '',
property2: 2
} as Test;
仅告诉编译器对象文字是Test
类型。对象文字与您的类具有相同的字段,但没有任何方法(因为没有人将它们放在那里)。
要创建类的实例,必须将new
运算符与类构造函数一起使用。如果要传递数据,则可以有一个接受数据并将其分配给当前实例的构造函数:
export class Test {
property1: any;
property2: any;
constructor(data: Partial<Test>) {
Object.assign(this, data);
}
sayHello(): string {
return 'hello';
}
}
let testData = new Test({
property1: '',
property2: 2
});
testData.sayHello(); //ok
答案 1 :(得分:1)
普通对象和类实例之间有区别。让我用Javascript解释一下。
当您写这篇文章时:
const x = { id: 0 };
它被翻译为:
const x = { id: 0 };
但是当你写这篇文章
class Test {
id = 0;
getId() {
return this.id;
}
}
const x = new Test();
它翻译为:
function Test() {
this.id = 0;
this.getId = () => this.id;
}
const x = new Test();
如您所见,在第一种情况下,没有任何功能。在第二种情况下,存在。
用Typescript编写时:
const x: Test = {id: 1};
这只是开发人员的便利,因为没有在Javascript中键入变量。这是您的皮棉机安装到位并告诉您错误的地方。
答案 2 :(得分:0)
Typescript只是语法帮助。它不会为代码带来新功能。例如,您的类语法将转换为普通的JavaScript。如果您像创建对象那样创建对象,那么它就是没有其他任何对象的对象。通过使用as Test
,IDE将向您显示属性并假装演员表。但是发生了更新,并且没有继承任何类属性。它仅是IDE支持。如果您希望testData
成为您的课程的实例,则必须这样做:
let testData = new Test();
testData.property1 = 'test';
然后您可以使用testData.sayHello()
答案 3 :(得分:0)
类型转换只是使编译器认为每个实例都是类型。它绝对不会为您创建该类的实际实例。
类型转换本质上是危险的,因为您会丢失编译时间检查,并且如果您的实际数据结构不符合您的界面的行为,则类型转换可能会在运行时中断。
存在类型转换的有效用例(例如,您具有来自远程端点的外部定义良好的JSON,并且您想定义其结构,我经常将响应类型转换为接口)。
但是,如果要在实例上使用实际方法,则必须创建它们。您必须使用构造函数并传递适当的值。