Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node.jsのtsサポートに関して再度理解する #88

Merged
merged 4 commits into from
Dec 17, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions app/routes/posts/node-typescript-support.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: "node.jsのtsサポートに関して再度理解する"
description: "Node.jsの`--experimental-strip-types`と、`--experimental-transform-types`について再度理解します。"
date: "2024/12/17"
updatedAt: "2024/12/17"
path: "node-typescript-support"
published: true
---

[2024年 ユウトの一人アドベントカレンダー](https://adventar.org/calendars/9980)の17日目の記事です。

## Intro

Node.jsの`--experimental-strip-types`と、`--experimental-transform-types`について再度理解します。

## おさらい

`--experimental-strip-types`を使うことで、TypeScriptファイルを実行できます。

この時は、TypeScriptの構文、EnumやNamespaceを使えません。
例えばEnumを使用すると、以下のようなエラーになります。

```
node:internal/modules/helpers:347
throw new ERR_INVALID_TYPESCRIPT_SYNTAX(error);
^

SyntaxError [ERR_INVALID_TYPESCRIPT_SYNTAX]: x TypeScript enum is not supported in strip-only mode
,-[1:1]
1 | ,-> export enum Foo {
2 | | FOO,
3 | | BAR
4 | `-> }
`----

at parseTypeScript (node:internal/modules/helpers:347:11)
at stripTypeScriptTypes (node:internal/modules/helpers:372:25)
at ModuleLoader.<anonymous> (node:internal/modules/esm/translators:475:16)
at #translate (node:internal/modules/esm/loader:433:12)
at ModuleLoader.loadAndTranslate (node:internal/modules/esm/loader:480:27) {
code: 'ERR_INVALID_TYPESCRIPT_SYNTAX'
}
```

`TypeScript enum is not supported in strip-only mode`となりますね。

そしてこれを解決するために生まれたのが、`--experimental-transform-types`になります。
このフラグを有効にすることで、TypeScript独自の構文でも実行可能になります。

ちなみにこの時、`--experimental-transform-types`は暗黙的に`--experimental-strip-types`も含んでいるので、おそらく今なら以下のスクリプトだけで十分なはずです。

```
"run": "node --experimental-transform-types index.ts",
```

```js
// > 暗黙的に`--experimental-strip-types`も含んでいる
// src: https://github.com/marco-ippolito/node/blob/e65928c6a10a6ae7983ccd3b3374d079ea3cb233/src/node_options.cc#L792-L798
AddOption("--experimental-transform-types",
"enable transformation of TypeScript-only"
"syntax into JavaScript code",
&EnvironmentOptions::experimental_transform_types,
kAllowedInEnvvar);
Implies("--experimental-transform-types", "--experimental-strip-types");
Implies("--experimental-transform-types", "--enable-source-maps");
```

## Amaroのスタックトレース保持方法

Node.jsではTypeScriptのトランスパイルにAmaroというswc typescript parserのラッパーを使用しています。

そしてこちらの面白いところが、スタックトレースのために、型を除いた分の空白をそのままにしておくそうです。

```ts
const amaro = require('amaro');
const { code } = amaro.transformSync("const foo: string = 'bar';", { mode: "strip-only" });
console.log(code); // "const foo = 'bar';"
```

型排除により詰めた分、元のコードとトランスパイル後のコードの行数は変わってしまうので、デバッグしづらくなるのを防いでいる感じですね。

## tsconfigは見ない

今回のNode.jsのtsサポートでは、tsconfigは読み込まれないようになっています。そのため、実行時の型チェックやエイリアスの設定、targetオプションの変更などはできないようになっています。

> TypeScript features that depend on settings within tsconfig.json, such as paths or converting newer JavaScript syntax to older standards, are intentionally unsupported. To get full TypeScript support, see Full TypeScript support.

ここら辺は公式の[full typescrit support](https://nodejs.org/api/typescript.html#full-typescript-support)を見るとわかります。tsxや、書かれてはないですがts-nodeを使用するようにみたいな感じらしいですね。

## まとめ

筆者としてはtsconfigを読み込まないのはエイリアス以外にも結構辛いポイントは出ると思っているので、それだったらts-nodeでいいんじゃないかなと思っている派です。

ただDenoとかBunの影響を受けて、これだけのユーザー数がいるOSSが、誰もが待ち望んだ機能を入れてくれたのはやっぱりすごいなと思うので、引き続き応援していきたいです。
Loading