如果你看一下 Observable 的签名:
export declare class Observable<T> implements Subscribable<T> {...}
你可以看到它需要论证T
. SomeThing<SomeType>
被称为generic并引用TypeScript 手册 https://www.typescriptlang.org/docs/handbook/generics.html,如果你看看通用恒等函数:
function identity(arg: any): any {
return arg;
}
使用时any当然是通用的,因为它会接受 arg 类型的任何和所有类型,但实际上我们正在丢失有关函数返回时该类型是什么的信息。如果我们传入一个数字,我们唯一拥有的信息就是any可以返回类型。
相反,我们需要一种捕获参数类型的方法,以便我们也可以使用它来表示返回的内容。在这里,我们将使用一个类型变量,一种特殊类型的变量,作用于类型而不是值。
function identity<T>(arg: T): T {
return arg;
}
您可以定义getTeachers(): any {}
如果您不关心此函数返回什么(或者您不知道)。它会起作用,但假设几个月后你要升级你的应用程序,你制作了一个漂亮的闪亮的新组件,它需要调用getTeachers()
。它会返回什么?Any. Cool. =挖掘了几个月的旧代码=重复N次(;
但是既然你知道函数的作用(返回 http.method,这是一个 Observable),你可以写getTeachers(): Observable<any>{}
。 ...闪亮的新组件;称呼getTeachers()
。它会返回什么?可观察的。很好,我可以订阅它并获得Any。好的,我可以处理这个...
在大多数情况/示例中,这就足够了。但你可以更具体。
如果你知道什么this.http.get('someUrl')
返回(假设它是响应正文中的 JSON 对象,标头“Content-Type”设置为“application/json” - 并且您使用 Respone.json() 来提取它),您可以编写getTeachers(): Observable<{}>{}
。现在我们知道这是一个Object.
最后,如果您知道该对象将具有与接口相同的属性Teacher,你可以这样定义你的函数:
getTeachers(): Observable<Teacher> {}
为什么没有转换语法将通用的任何类型的 res.json() 转换为更具体的类型 Teacher?
这里没有转换,数据保持不变。您只是通过声明数据为特定类型来提供该数据的“描述”。根据您所了解的信息。没有魔法(:.
为什么建议 Teacher 使用 TypeScript 接口而不是 TypeScript 类?
在此背景下Teacher
可以是类或接口。在这里没关系,TypeScript 会从类或接口读取信息。如果您不会在任何其他上下文中使用 Teacher,则可以创建一个界面(它不会编译为 JavaScript,因此代码较少)。如果您在其他地方使用它,例如您需要一个实例Teacher
:
let new_guy = new Teacher();
那么你应该将 Teacher 声明为一个类。