英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论