TSC编译错误 (TS2307) 在使用Deno API时发生。

huangapple go评论60阅读模式
英文:

TSC Compile Error (TS2307) when using the Deno API

问题

I have a little ts project that should be compiled into js.
Since I don't know with which runtime (Deno, Bun or Node) will run, I really need to compile it to js and cannot use the Deno built-in compiler.

When I try to compile now, the compiler throws an error:

 error TS2304: Cannot find name 'Deno'.

Line 34                 version: Deno.version.deno

This is my tsconfig file:

{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es6",
    "strict": true,
    "esModuleInterop": true,
    "moduleResolution": "node",
    "baseUrl": "./src",
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "types": ["bun-types"]
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

Do you know how I can fix this issue?

I know I could add // @ts-ignore right before, but I would prefer to find a proper configuration.

Thank you in advance!

英文:

I have a little ts project that should be compiled into js.
Since I don't know with which runtime (Deno, Bun or Node) will run, I really need to compile it to js and can not use the Deno built-in compiler.

When I try to compile now the compiler throws an error:

 error TS2304: Cannot find name 'Deno'.

Line 34                 version: Deno.version.deno

This is my tsconfig file:

{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es6",
    "strict": true,
    "esModuleInterop": true,
    "moduleResolution": "node",
    "baseUrl": "./src",
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "types": ["bun-types"]
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

Do you know how I can fix this issue?

I know I could add // @ts-ignore right before but I would prefer to find a proper configuration.

Thank you in advance!

答案1

得分: 2

I understand your instructions. Please note that I am a text-based AI and cannot execute or validate code.

英文:

When writing isomorphic TypeScript (targeted at multiple runtimes/environments), you won't be able to reliably depend on any values which aren't common to every environment without using feature detection. And because of this, you also can't safely include any ambient library types during compilation — for example: types like Node.js (@types/node), Bun (bun-types), Deno (deno.ns, deno.window, etc.), browser/DOM (@types/web, dom, dom.iterable, etc.), or others — which makes it even more complicated.

TypeScript offers a helpful feature called type predicates that can be used with type guard functions to perform these kinds of validations at runtime — and they'll also inform the compiler that values are of the expected types and are safe to use as such.

You can reference the Deno namespace type declarations at the project's GitHub repository — for example, here's a direct link to the line for Deno.version.deno for the current CLI version as I write this answer (v1.32.4): https://github.com/denoland/deno/blob/v1.32.4/cli/tsc/dts/lib.deno.ns.d.ts#L4708

In your code, you can feature-detect for the Deno version value like this:

./src/example.mts:

// The following triple-slash directives aren't necessary when using
// the TSConfig in this answer, but I'm including them here so that the module
// can be type-checked in isolation, apart from the config file (e.g. by Deno):
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
/// <reference path="./types/global.d.ts" />

function isObject<T>(value: T): value is T & object {
  return typeof value === "object" && value != null;
}

// There's a global Deno variable
if ("Deno" in globalThis) {
  // But we don't yet know what type it is
  const { Deno } = globalThis as Record<string, unknown>;
  // It's an object
  if (isObject(Deno)) {
    // And it has a "version" key that's also an object
    if ("version" in Deno && isObject(Deno.version)) {
      // And that object has a "deno" key that's a string
      if ("deno" in Deno.version && typeof Deno.version.deno === "string") {
        // Only in this scope can we safely access it with confidence
        console.log("Deno version:", Deno.version.deno);
      } else {
        console.log(`There's no "deno" string key in Deno.version`);
      }
    } else {
      console.log(`There's no "version" object key in Deno`);
    }
  } else {
    console.log("Deno is not an object");
  }
} else {
  console.log("There's no global Deno");
}


For completeness, here are the other files in my reproduction directory for your question:

./package.json:

{
  "name": "so-76034796",
  "version": "0.1.0",
  "type": "module",
  "scripts": {
    "compile": "tsc"
  },
  "devDependencies": {
    "typescript": "^5.0.4"
  }
}

./tsconfig.json:

{
  "compilerOptions": {
    "strict": true,
    "exactOptionalPropertyTypes": true,
    "noImplicitOverride": true,
    "noImplicitReturns": true,
    "noUncheckedIndexedAccess": true,

    "removeComments": true,
    // "inlineSourceMap": true,
    // "inlineSources": true,

    "forceConsistentCasingInFileNames": true,

    "module": "esnext",
    "moduleDetection": "force",
    "moduleResolution": "nodenext",
    // "moduleResolution": "bundler",
    // "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "esModuleInterop": true,

    "target": "esnext",
    "lib": ["esnext"],

    // "jsx": "react-jsx",

    "outDir": "dist",
    // "noEmit": true,

    "typeRoots": ["./src/types"]
  },
  "include": ["src/**/*"]
}

> I've included these types from the Console API because it's available in all of the environments mentioned to be targeted. Otherwise, you'd need to feature-detect for it as well:

./src/types/global.d.ts:

/**
 * @see https://github.com/microsoft/TypeScript/blob/v5.0.4/lib/lib.dom.d.ts#L17498
 * 
 * For Node.js, refer to:
 * - [global](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/04c9ac7555c9fd1562aea37475af4e176db0019a/types/node/globals.d.ts#L28)
 * - [console](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/04c9ac7555c9fd1562aea37475af4e176db0019a/types/node/console.d.ts#L66)
 */
interface Console {
  assert(condition?: boolean, ...data: any[]): void;
  clear(): void;
  count(label?: string): void;
  countReset(label?: string): void;
  debug(...data: any[]): void;
  dir(item?: any, options?: any): void;
  dirxml(...data: any[]): void;
  error(...data: any[]): void;
  group(...data: any[]): void;
  groupCollapsed(...data: any[]): void;
  groupEnd(): void;
  info(...data: any[]): void;
  log(...data: any[]): void;
  table(tabularData?: any, properties?: string[]): void;
  time(label?: string): void;
  timeEnd(label?: string): void;
  timeLog(label?: string, ...data: any[]): void;
  timeStamp(label?: string): void;
  trace(...data: any[]): void;
  warn(...data: any[]): void;
}

declare var console: Console;

Compiling with vanilla tsc and running in Node and Deno:

so-76034796 % npm install

added 1 package, and audited 2 packages in 445ms

found 0 vulnerabilities

so-76034796 % npm run compile

> so-76034796@0.1.0 compile
> tsc

so-76034796 % deno check src/example.mts

so-76034796 % deno run src/example.mts
Deno version: 1.32.4

so-76034796 % deno run dist/example.mjs
Deno version: 1.32.4

so-76034796 % node dist/example.mjs
There's no global Deno

so-76034796 % node --version
v18.16.0

so-76034796 % npm --version
9.5.1

so-76034796 % deno --version
deno 1.32.4 (release, aarch64-apple-darwin)
v8 11.2.214.9
typescript 5.0.3

huangapple
  • 本文由 发表于 2023年4月17日 19:41:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76034796.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定