Upgrade to Pro — share decks privately, control downloads, hide ads and more …

推論された型の移植性エラーTS2742に挑む

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

 推論された型の移植性エラーTS2742に挑む

Avatar for teamLab

teamLab PRO

May 25, 2025
Tweet

More Decks by teamLab

Other Decks in Programming

Transcript

  1. The inferred type of 'returnValue' cannot be named without a

    reference to ''../../middle-lib/node_modules/base-lib/dist/index.js'. This is likely not portable. A type annotation is necessary. ts(2742) 'returnValue' の推論された型には、'../../middle-lib/node_modules/base- lib/dist/index.js' への参照なしで名前を付けることはできません。これは、移植性がない可能性 があります。型の注釈が必要です。ts(2742) ? | 4 of 20
  2. base-libとmiddle-libのd.ts base-lib/index.d.ts middle-lib/index.d.ts base-lib に依存している base-lib index.d.ts index.js middle-lib index.d.ts

    index.js main index.ts export type SomeComplexType = { // (中身は余り関係無いが、単純すぎるとインライン化されるみたい) num: number; nest?: SomeComplexType; }; export declare const returnsInferredSomeComplexType: () => SomeComplexType; export declare const wrappedReturnsInferredSomeComplexType: () => import("base-lib").SomeComplexType; | 9 of 20
  3. mainパッケージでの問題 このコードをコンパイルしたとき、d.tsはどのように出力すべきか? base-lib index.d.ts index.js middle-lib index.d.ts index.js main index.ts

    index.d.ts mainパッケージで以下の様なコードを書いたとする。 import { wrappedReturnsInferredSomeComplexType } from "middle-lib"; export const mainValue = wrappedReturnsInferredSomeComplexType(); // ^| base-libの型SomeComplexTypeに推論されるが... import { wrappedReturnsInferredSomeComplexType } from "middle-lib"; export const mainValue: ???; | 10 of 20
  4. ダメな例 mainパッケージ基準の相対パスで指定 middle-libの内部ディレクトリを参照 -> node_modulesの構造はパッケージマネージャによって異なるのでNG 大まかには、hoistingするかどうかで変わる import { getBaseLibValue }

    from "middle-lib"; import type { SomeComplexType } from "../node_modules/middle-lib/node_modules/base-lib/index.js"; export const mainValue: SomeComplexType; import { getBaseLibValue } from "middle-lib"; import type { SomeComplexType } from "middle-lib/node_modules/base-lib/index.js"; export const mainValue: SomeComplexType; | 11 of 20
  5. これは…? 一見よさそうに見えるが、middle-lib --> base-libとmain --> base-libの指す先が同じとは限らな い 別のバージョンに依存していた場合は、実装と型が乖離して壊れる可能性がある main middle-lib

    base-lib@1 base-lib@2 -> 移植性がないとして TS2742 エラーを発生させる import { getBaseLibValue } from "middle-lib"; import type { SomeComplexType } from "base-lib"; export const mainValue: SomeComplexType; import { wrappedReturnsInferredSomeComplexType } from "middle-lib"; import type { SomeComplexType } from "???"; // 無理!!! export const mainValue: ???; // 無理!!! | 12 of 20
  6. ユーザ側(main)の対策 エラーの言うとおり、型注釈を明示的に書く … 型の注釈が必要です。ts(2742) これで解決!..🤔 型推論が便利なときは書きたくない… あと単に冗長 import { wrappedReturnsInferredSomeComplexType

    } from "ref"; export const returnValue: ReturnType< typeof wrappedReturnsInferredSomeComplexType > = wrappedReturnsInferredSomeComplexType(); const validator: () => { name: string } = createValidator( // ^ ここは書きたくないわけで z.object({ name: z.string() }), ); | 14 of 20
  7. ユーザ側(main)のworkaround tsconfigの declaration を false にする 有効なd.tsを出力できないからエラーになっているので、そもそも出力しなければエラーにならない 直接依存に追加してimportする import type

    {} from "base-lib" をmainのどこかに書く コンパイル対象のどこかに base-lib への参照があれば、それと同じ先に解決される ライブラリ側が依存しているバージョンと別のバージョンに解決してしまう可能性があるので要注意 TS5.5以上に上げてみる Consulting package.json Dependencies for Declaration File Generation TS5.4以前でTS2742エラーが発生している場合、偽陽性かもしれない 後述の対策をpnpm patch | 15 of 20