正如我所看到的,由TypeScript开发人员编写的examples,他们使用某种存根来实现与JavaScript的互操作性:
declare module Backbone {
export class Model {
constructor (attr? , opts? );
get(name: string): any;
set(name: string, val: any): void;
set(obj: any): void;
save(attr? , opts? ): void;
destroy(): void;
bind(ev: string, f: Function, ctx?: any): void;
toJSON(): any;
}
...
}
interface JQuery {
fadeIn(): JQuery;
fadeOut(): JQuery;
focus(): JQuery;
html(): string;
html(val: string): JQuery;
show(): JQuery;
addClass(className: string): JQuery;
removeClass(className: string): JQuery;
append(el: HTMLElement): JQuery;
val(): string;
val(value: string): JQuery;
attr(attrName: string): string;
}
这看起来很奇怪。我可以省略编写这样的存根,只需使用jQuery
对象并调用它的方法吗?我希望,这是可能的,因为TypeScript是JavaScript的超集,如果它可以在JavaScript中使用,那么它也可能在TypeScript中成为可能。从TypeScript中调用JavaScript代码的最佳方法是什么?
答案 0 :(得分:2)
它们不是存根,它们是类型声明。由于javascript是无类型的,因此需要将类型添加到函数和方法签名中。如果没有这些打字稿,则无法帮助您进行任何静态分析。
例如:
confirm
函数打开一个弹出窗口,询问您一个问题,并根据您是否点击'ok'或'cancel'获得布尔值true或false。在普通的旧Javascript中,您可以像这样调用函数:
var x = prompt(1 + 1) + "hello world";
这没有意义,因为prompt需要一个字符串参数并返回一个布尔值。 Typescript通过在标准的lib.d.ts中添加此声明来帮助:
declare function confirm(message?: string): boolean;
因此,我上面编写的代码会使用typescript编译器导致编译错误。
答案 1 :(得分:1)
您可以完全省略这些声明并生成有效的Typescript代码;这些说明的目的是添加有关vanilla Javascript API的返回类型的信息,以便从Typescript的静态类型检查中受益。如果您不使用它们,那么从普通JS库导入的所有内容都将返回类型为any
的值,而Typescript无法对其进行检查。
这种做法被称为type declaration files,您可能不需要自己编写:最流行的Javascript库可以在线获得数百个这样的声明文件。
答案 2 :(得分:1)
TypeScript会阻止您使用不存在的变量。例如,如果我只在.ts
文件中包含此代码:
$("#myElement").hide();
TypeScript会将其输出到.js
文件中;但是,它也会抛出一个编译错误,告诉我$
还没有被定义。这是为了防止我犯错误。
因此,当我使用JavaScript库(如jQuery)时,如果没有首先告诉编译器有关JS代码中的变量(例如$
),编译器会抛出一个错误告诉我他们并非如此。定义。这实际上可能是我的错误...编译器不知道,因为我还没有告诉它,它无法正确分析JavaScript代码以找出答案。
为了解决这个问题,我可以继续告诉编译器 至少 定义带有any
的环境定义时,这不是错误类型:
declare var $: any;
现在我的.ts
文件中出现了错误,因为我已经告诉编译器这个变量存在于TypeScript代码之外并且使用any
定义它类型,我告诉它这个变量可以以任何方式使用(这是该语言的可选静态类型部分)。
但是,没有关于变量的类型信息不是优选的。它使用起来很容易,因为对变量的使用没有任何限制。为了解决这个问题,我可以继续描述一下$
的类型,但是这个类型定义已经存在,所以我可以使用tsd
将它安装到我的应用程序中:
tsd install jquery
然后在我的应用程序中使用下载的jquery.d.ts
文件。