如何在具有相同名称的.js文件中从.d.ts文件中导入类型?

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

How can I import types from a .d.ts file in a .js file with the same name

问题

I'm providing the translation of the non-code content:

"I’m writing JavaScript code and want type safety with TypeScript via JSDoc.

Because it’s just nicer to write types in TypeScript, I wanted to put the type definitions in a .d.ts file right next to my .js file:

// person.d.ts
export type Person = {
  name: string;
}
// person.js

/** @type {import("./person").Person} */
let person;

person = {
  name2: "sdf", // <-- this should error, but does not
};

The issue is that this seems to break the TypeScript checker.

If I rename person.d.ts to foo.d.ts and import ./foo, it works.

What is strange is that TypeScript seems to see and understand the type; it just doesn’t properly interpret it:

如何在具有相同名称的.js文件中从.d.ts文件中导入类型?

Am I doing something wrong?

EDIT: Here is my tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "allowJs": true,
    "checkJs": true,
    "rootDir": "."
  },
  "include": ["./**/*.js", "./**/*.ts"]
}
英文:

I’m writing JavaScript code and want type safety with TypeSript via JSDoc.

Because it’s just nicer to write types in TypeScript I wanted to put the type definitions in a .d.ts file right next to my .js file:

// person.d.ts
export type Person = {
  name: string;
}
// person.js

/** @type {import(&quot;./person&quot;).Person} */
let person;

person = {
  name2: &quot;sdf&quot;, // &lt;-- this should error, but does not
};

The issue is, that this does seem to break the TypeScript checker.

If I rename person.d.ts to foo.d.ts and import ./foo instead, it works.

What is strange, is that TypeScript seems to see and understand the type, it just doesn’t properly interpret it:

如何在具有相同名称的.js文件中从.d.ts文件中导入类型?

Am I doing something wrong?

EDIT: here is my tsconfig.json

{
  &quot;compilerOptions&quot;: {
    &quot;target&quot;: &quot;esnext&quot;,
    &quot;allowJs&quot;: true,
    &quot;checkJs&quot;: true,
    &quot;rootDir&quot;: &quot;.&quot;
  },
  &quot;include&quot;: [&quot;./**/*.js&quot;, &quot;./**/*.ts&quot;]
}

答案1

得分: 2

你所经历的实际上是一个非常晦涩的tsc "特性"。

考虑以下的tsconfig

{
  "include": [
    "**/*.js",
    "**/*.ts"
  ],
  "compilerOptions": {
    "rootDir": ".",
    "listFiles": true,
    "module": "commonjs",
    "allowJs": true,
    "checkJs": true,
    "noEmit": true,
    "skipLibCheck": true
  }
}

现在运行 tsc

/home/user/source/module/node_modules/typescript/lib/lib.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.es5.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.dom.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.webworker.importscripts.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.scripthost.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.decorators.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.decorators.legacy.d.ts
/home/user/source/module/src/person.d.ts

你可以看到编译器只捕捉到了 person.d.ts,尽管 person.js 明显存在。同时也没有报告错误。

现在从 tsconfig.json 中移除 include 部分:

$ tsc
src/person.js:7:5 - error TS2322: Type 'name2: string; }' is not assignable to type 'Person'.
  Object literal may only specify known properties, but 'name2' does not exist in type 'Person'. Did you mean to write 'name'?

7     name2: "sdf", // <-- this should error, but does not
      ~~~~~~~~~~~~

/home/user/source/module/node_modules/typescript/lib/lib.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.es5.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.dom.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.webworker.importscripts.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.scripthost.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.decorators.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.decorators.legacy.d.ts
/home/user/source/module/src/person.d.ts
/home/user/source/module/src/person.js

Found 1 error in src/person.js:7

现在 神奇地 编译器捕捉到了 person.jsperson.d.ts。为什么呢?

似乎当使用 include 时,tsc 会因为某种原因排除它认为可能在先前运行的 tsc 中生成(自动生成)的文件。例如,如果你有一个 person.ts 文件并运行 tsc,它会生成一个名为 person.jsperson.d.ts 的文件(在 tsconfig.json 中将 declaration 设置为 true)。

我见过的唯一解释是这份技术上已过时的文档

请注意,编译器不包括可能是输出的文件;例如,如果输入包括 index.ts,那么 index.d.tsindex.js 就会被排除。总的来说,不建议将只有扩展名不同的文件放在一起。

简而言之,一个解决方法是完全删除 include 部分。在这种情况下,它是不需要的,通常只有在你有一个相当复杂的存储库时才需要。

另外,正如文档建议的,你也可以将你的类型移动到一个完全不同的文件夹中,或者全部放在一个单一的文件中。

英文:

What you're experiencing is actually a very obscure tsc "feature".

Consider the following tsconfig:

{
  &quot;include&quot;: [
    &quot;**/*.js&quot;,
    &quot;**/*.ts&quot;
  ],
  &quot;compilerOptions&quot;: {
    &quot;rootDir&quot;: &quot;.&quot;,
    &quot;listFiles&quot;: true,
    &quot;module&quot;: &quot;commonjs&quot;,
    &quot;allowJs&quot;: true,
    &quot;checkJs&quot;: true,
    &quot;noEmit&quot;: true,
    &quot;skipLibCheck&quot;: true
  }
}
$ tree -L 2
.
├── node_modules
│&#160;&#160; ├── reverse-line-reader
│&#160;&#160; └── typescript
├── package.json
├── src
│&#160;&#160; ├── person.d.ts
│&#160;&#160; └── person.js
├── tsconfig.json
└── yarn.lock

Now run tsc:

/home/user/source/module/node_modules/typescript/lib/lib.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.es5.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.dom.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.webworker.importscripts.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.scripthost.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.decorators.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.decorators.legacy.d.ts
/home/user/source/module/src/person.d.ts

You can see only person.d.ts is picked up by the compiler, even though person.js clearly exists. There are also no reported errors.

Now remove the include section from tsconfig.json:

$ tsc
src/person.js:7:5 - error TS2322: Type &#39;{ name2: string; }&#39; is not assignable to type &#39;Person&#39;.
  Object literal may only specify known properties, but &#39;name2&#39; does not exist in type &#39;Person&#39;. Did you mean to write &#39;name&#39;?

7     name2: &quot;sdf&quot;, // &lt;-- this should error, but does not
      ~~~~~~~~~~~~

/home/user/source/module/node_modules/typescript/lib/lib.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.es5.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.dom.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.webworker.importscripts.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.scripthost.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.decorators.d.ts
/home/user/source/module/node_modules/typescript/lib/lib.decorators.legacy.d.ts
/home/user/source/module/src/person.d.ts
/home/user/source/module/src/person.js

Found 1 error in src/person.js:7

Now magically both person.js and person.d.ts are picked up by the compiler. Why?

It seems that when using include, tsc will for some reason exclude files it thinks may have been emitted (auto-generated) by tsc in a previous run. For example, if you had a person.ts file and ran tsc, it would produce a file named person.js and person.d.ts (with declaration set to true in tsconfig.json).

The only explanation I have ever seen is this document which is technically deprecated:

> Please note that the compiler does not include files that can be possible outputs; e.g. if the input includes index.ts, then index.d.ts and index.js are excluded. In general, having files that differ only in extension next to each other is not recommended.

However, it appears to still be true to this day.

In short, one solution is to simply remove the include section entirely. It is not needed in this case, and usually not unless you have a fairly complex repository.

Alternatively, as the documentation suggests, you can move your types into a different folder entirely, or all into a monolithic file.

huangapple
  • 本文由 发表于 2023年5月11日 18:48:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76226793.html
匿名

发表评论

匿名网友

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

确定