2019年12月16日月曜日

TypeScriptでd.ts内でimportすると外部でその型が読み込めなくなるのを解決した的なお話

  • このエントリーをはてなブックマークに追加

タイトルからするとよくわかりづらいんだけど。
React Native x TypeScriptで型をtypesディレクトリの中につらつらと書く感じで自分は開発してる。
そうするとどこでもtype Hogeを読み出すことができるんだけど、d.ts内でimport { FirebaseFirestoreTypes } from '@react-native-firebase/firestore';みたいにすると途端にHogeが読み出せなくなってしまう的な。

ということで今日はそれを解決するには的なお話をば。

# ディレクトリ
ios/
android/
src/
  components/
  screens/
    HomeScreen.tsx
    DetailScreen.tsx
  types/
    hoge.d.ts
    foo.d.ts

# hoge.d.ts
type Hoge = {
  hoge1:number,
  hoge2:string,
}

type ImageWithSize = {
  src:string,
  width:number,
  height:number,
}

# foo.d.ts
import { ImageWithSize } from "./hoge";
import { FirebaseFirestoreTypes } from '@react-native-firebase/firestore';

type Foo = {
  img:ImageWithSize,
  createdAt:FirebaseFirestoreTypes.Timestamp,
}

# DetailScreen.tsx
const [foo,setFoo] = useState<Foo>({...});

とりあえずざっくりとこんな感じの構成だとして。
typesディレクトリ内に諸々適当に型を書いている。

DetailScreen.tsxにてfooが型Fooであるとは普通思うんだけど、どう考えてもanyになってしまっている。
foo.d.ts内のimport文を無くしてあげれば問題ないんだけど、そうするとFooの二つのフィールドはany型となってしまいこれもおかしい。

https://stackoverflow.com/questions/39040108/import-class-in-definition-file-d-ts#answer-51114250
まぁとりあえず結果を先に書くと下記のような感じで書けば問題なくなった。

# foo.d.ts
type Foo = {
  img:import("./hoge").ImageWithSize,
  createdAt:import("@react-native-firebase/firestore").FirebaseFirestoreTypes.Timestamp,
}
d.ts files are treated as an ambient module declarations only if they don't have any imports. If you provide an import line, it's now treated as a normal module file, not the global one, so augmenting modules definitions doesn't work.

So that's why all the solutions we discussed here don't work. But fortunately, since TS 2.9 we are able to import types into global modules declaration using import() syntax:

d.ts内でimport文を書くと通常のモジュールと同等に扱われてしまうので、意図しない動作になった的な。
だからimport()っていう形でやってあげればいいんだよ的な。

とりあえず解決できてよかった。
d.tsをimportするとか地味に面倒だしなるべくimport文書きたくないから解決策が見つかってよかった的なみたいな。

1 件のコメント:

Adsense