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