使用TypeScript

使用外部类型定义

JavaScript 和 TypeScript 在 Deno 运行时都可以作为第一语言。这说明,它需要完全合格的模块名,包括扩展名(或提供正确媒体类型的服务器)。另外,Deno 不能解析”魔术”模块。

然而开箱即用 TypeScript 编译器要依赖没有扩展名的模块和 Node.js 模块解析逻辑将类型应用到 JavaScript 模块。

为了弥合这一鸿沟,在不使用‘魔术’解析的情况,Deno 支持三种类指向类型定义文件的方式。

编译提示

如果你正在引入一个知道类型定义文件位置的 JavaScript 模块,你可以在 import 的时候以编译提示的形式指定类型定义。 编译提示告知 Deno 引入的 JavaScript 代码相关的 .d.ts 文件的位置。这个提示是 @deno-types ,指定的值是在编译器中使用的,而不是在 JavaScript 模块中使用。例如,你有一个 foo.js ,并且你知道它的类型文件是 foo.d.ts ,那么你的代码就会是这样的:

  1. // @deno-types="./foo.d.ts"
  2. 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 提供它的类型文件位置,那它的内容看起来像这样:

  1. /// <reference types="./foo.d.ts" />
  2. 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执行你的应用时要使用哪个配置文件。

  1. deno run -c tsconfig.json mod.ts

以下是当前 Deno 支持的设置和它们的默认值:

  1. {
  2. "compilerOptions": {
  3. "allowJs": false,
  4. "allowUmdGlobalAccess": false,
  5. "allowUnreachableCode": false,
  6. "allowUnusedLabels": false,
  7. "alwaysStrict": true,
  8. "assumeChangesOnlyAffectDirectDependencies": false,
  9. "checkJs": false,
  10. "disableSizeLimit": false,
  11. "generateCpuProfile": "profile.cpuprofile",
  12. "jsx": "react",
  13. "jsxFactory": "React.createElement",
  14. "lib": [],
  15. "noFallthroughCasesInSwitch": false,
  16. "noImplicitAny": true,
  17. "noImplicitReturns": true,
  18. "noImplicitThis": true,
  19. "noImplicitUseStrict": false,
  20. "noStrictGenericChecks": false,
  21. "noUnusedLocals": false,
  22. "noUnusedParameters": false,
  23. "preserveConstEnums": false,
  24. "removeComments": false,
  25. "resolveJsonModule": true,
  26. "strict": true,
  27. "strictBindCallApply": true,
  28. "strictFunctionTypes": true,
  29. "strictNullChecks": true,
  30. "strictPropertyInitialization": true,
  31. "suppressExcessPropertyErrors": false,
  32. "suppressImplicitAnyIndexErrors": false,
  33. "useDefineForClassFields": false
  34. }
  35. }

支持的值以及应用案例文档请参见 typescript 文档

说明: 以上未列出的选项要么Deno 不支持,要么在 TypeScript 文档中的废弃/试验列表中。