使用TypeScript
使用外部类型定义
JavaScript 和 TypeScript 在 Deno 运行时都可以作为第一语言。这说明,它需要完全合格的模块名,包括扩展名(或提供正确媒体类型的服务器)。另外,Deno 不能解析”魔术”模块。
然而开箱即用 TypeScript 编译器要依赖没有扩展名的模块和 Node.js 模块解析逻辑将类型应用到 JavaScript 模块。
为了弥合这一鸿沟,在不使用‘魔术’解析的情况,Deno 支持三种类指向类型定义文件的方式。
编译提示
如果你正在引入一个知道类型定义文件位置的 JavaScript 模块,你可以在 import 的时候以编译提示的形式指定类型定义。
编译提示告知 Deno 引入的 JavaScript 代码相关的 .d.ts
文件的位置。这个提示是 @deno-types
,指定的值是在编译器中使用的,而不是在 JavaScript 模块中使用。例如,你有一个 foo.js
,并且你知道它的类型文件是 foo.d.ts
,那么你的代码就会是这样的:
// @deno-types="./foo.d.ts"
import * as foo from "./foo.js";
它的值和引入模块的解析逻辑是一样的,意味着文件需要扩展名,并且是相对当前模块的。当然它也支持远程路径。
这个提示会影响接下来的 import
语句(或 export ... from
语句),@deno-types
的值会在编译的时候替换指定的模块。如上面的例子,Deno 编译器会加载 ./foo.d.ts
而不是 ./foo.js
。但是 Deno 运行程序的时候仍然会加载 ./foo.js
。
JS文件中的三斜杠reference指令
如果你正在组织 Deno 要使用的模块,你想要通知 Deno 他的类型文件的位置,你可以在实际代码位置使用三斜杠指令。 例如,你有一个叫 ‘foo.js’ 的JavaScript 模块,你想要在这个文件中给 Deno 提供它的类型文件位置,那它的内容看起来像这样:
/// <reference types="./foo.d.ts" />
export const foo = "foo";
Deno 能够看到它,尽管运行时的时候会加载 foo.js
,编译器在检查类型的时候会使用 foo.d.ts
。
指令的值的解析逻辑和引入模块的解析逻辑一样,那么它是相对当前文件路径,必须有文件扩展名。当然它也支持远程路径。
X-TypeScript-Types 自定义 header
如果你正在组织 Deno 要使用的模块,你想要通知 Deno 他的类型文件的位置,你可以使用一个自定义的 HTTP header X-TypeScript-Types
来告诉 Deno 那个文件的位置。
这个 header 的工作原理和上面提到的三斜杠指令是一样的,它只是意味着 JavaScript 文件内容本身并不需要修改,类型定义文件的位置可以由服务器本身决定。
并不是所有的类型定义都是支持的
Deno 会使用编译器提示来加载指定的 .d.ts
,但是一些 .d.ts
包含不支持的特性。尤其,一些 .d.ts
使用模块解析逻辑来加载其他包中的类型定义。例如,一个类型包含 node
的类型引用指令用来解析类似 ./node_modules/@types/node/index.d.ts
的路径。由于它依赖非相关的‘魔术’解析,Deno 不支持这种。
为什么不在 TypeScript 文件中使用三斜杠类型 reference ?
TypeScript 编译器支持三斜杠指令,包括类型引用指令。如果 Deno 用它,那么就会干扰 TypeScript 编译器的行为。Deno 只会去 JavaScript 或 JSX 文件中找这个指令。
自定义 TypeScript 编译器选项
在 Deno 的生态中,为了默认遵从 TypeScript 理想的严格模式,所有的严格标识都可用。
然而,为了提供定制化,类似 tsconfig.json
这样的定制化配置文件必须在程序执行时提供给 Deno 。
你需要设置 -c
参数显示地告诉Deno执行你的应用时要使用哪个配置文件。
deno run -c tsconfig.json mod.ts
以下是当前 Deno 支持的设置和它们的默认值:
{
"compilerOptions": {
"allowJs": false,
"allowUmdGlobalAccess": false,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"alwaysStrict": true,
"assumeChangesOnlyAffectDirectDependencies": false,
"checkJs": false,
"disableSizeLimit": false,
"generateCpuProfile": "profile.cpuprofile",
"jsx": "react",
"jsxFactory": "React.createElement",
"lib": [],
"noFallthroughCasesInSwitch": false,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitUseStrict": false,
"noStrictGenericChecks": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"preserveConstEnums": false,
"removeComments": false,
"resolveJsonModule": true,
"strict": true,
"strictBindCallApply": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"strictPropertyInitialization": true,
"suppressExcessPropertyErrors": false,
"suppressImplicitAnyIndexErrors": false,
"useDefineForClassFields": false
}
}
支持的值以及应用案例文档请参见 typescript 文档 。
说明: 以上未列出的选项要么Deno 不支持,要么在 TypeScript 文档中的废弃/试验列表中。