- お世話になっているライブラリ NativeBase でおきていた TS エラーについて理解できてなかったので調べてみた
環境
- react-natve: 0.57.8
- natibe-base: 2.8.0
- react-native-keyboard-aware-scroll-view: 0.5.0
ドキュメント
NativeBase v2.8.0 - CheatSheet
<Content> Replacing React Native KeyboardAwareScrollView
APSL/react-native-keyboard-aware-scroll-view - Props
All the ScrollView/FlatList props will be passed.
疑問
natibe-base 2.8.0 の <content>
で onScroll
使うと (実際には使えるにも関わらず) TS2339 エラーになるのはなぜか?
<Content onScroll={}>
と書くと TSエラーになるError:(42, 9) TS2339: Property 'onScroll' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Content> & Readonly<{ children?: ReactNode; }> & R...'.
ドキュメントに書かれている事
-
natibe-base の <content> コンポーネント
はreact-native-keyboard-aware-scroll-view の <KeyboardAwareScrollView>
に変換される -
<KeyboardAwareScrollView>
はreact-native の <ScrollView>
のプロパティが使える -
<ScrollView>
はonScroll
プロパティを持っている
-
<Content onScroll={}>
は使い方として正しいよね?わかっている事
onScroll={}
自体はちゃんと使えていて、動作している- Content の代わりに
react-native の ScrollView
を使用すると TS エラーにならない<ScrollView onScroll={}>
と書いた場合は TS エラーにならない
- Content の代わりに
react-native-keyboard-aware-scroll-view' のKeyboardAwareScrollView
を使用すると TS エラーにならない<KeyboardAwareScrollView onScroll={}>
と書いた場合は TS エラーにならない
(推測)
- NateveBase に同梱されている TypeScript の 宣言ソースファイル(Declaration source file)(=
node_modules/native-base/index.d.ts
) になにか原因がありそう
コードを追ってみた
NativeBase の TypeScript の 宣言ソースファイル
node_modules/native-base/index.d.ts
NativeBase の Content コンポーネント のソースコード
node_modules/native-base/src/basic/Content.js
NativeBase が利用している
react-native-keyboard-aware-scroll-view
の TypeScript の 宣言ソースファイルnode_modules/native-base/node_modules/react-native-keyboard-aware-scroll-view/index.d.ts
わかった事
<Content onScroll={}>
は有効native-base の index.d.ts (型定義ファイル) に不備がある
- Content の interface が
react-native-keyboard-aware-scroll-view
の型定義ファイルを extend していない - この為、
KeyboardAwareScrollView
のプロパティ(ひいてはScrollView
のプロパティ)を使うと、TS エラーになる
- Content の interface が
react-native-keyboard-aware-scroll-view の index.d.ts には不備がない
interface KeyboardAwareScrollViewProps
は react-native のScrollViewProperties
を extends している
// node_modules/native-base/index.d.ts declare module "native-base" { // KeyboardAwareScrollViewProps は import されてない import * as React from "react"; import * as ReactNative from "react-native"; namespace NativeBase { // node_modules/native-base/index.d.ts:159 // ★ここを Content extend KeyboardAwareScrollViewProps とすれば、onScroll が TS エラーにならない /** * see Widget Content.js */ interface Content { /** * The theme prop can be applied to any component of NativeBase. */ refreshing?: boolean; refreshControl?: object; theme?: Object; padder?: boolean; disableKBDismissScroll?: boolean; enableResetScrollToCoords?: boolean; contentOffset?: Object; scrollEnabled?: boolean; style?: ReactNative.ViewStyle | Array<ReactNative.ViewStyle>; contentContainerStyle?: ReactNative.ViewStyle | Array<ReactNative.ViewStyle>; keyboardShouldPersistTaps?: string; keyboardDismissMode?: string; } }
// node_modules/native-base/src/basic/Content.js import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view"; render() { // 確かに `react-native-keyboard-aware-scroll-view` の `<KeyboardAwareScrollView>` コンポーネントを `render()` している return variable.isIphoneX ? ( <KeyboardAwareScrollView > {this.props.children} </KeyboardAwareScrollView> ) : ( <KeyboardAwareScrollView > {this.props.children} </KeyboardAwareScrollView> );
// node_modules/native-base/node_modules/react-native-keyboard-aware-scroll-view/index.d.ts import { ScrollViewProperties, ListViewProperties, FlatListProperties } from 'react-native' // react-native の `ScrollViewProperties` を extends している interface KeyboardAwareScrollViewProps extends KeyboardAwareProps, ScrollViewProperties {} export class KeyboardAwareScrollView extends React.Component< KeyboardAwareScrollViewProps, KeyboardAwareState > {}
対応方法
native-base
に下記の修正を Pull Request する- 型定義ファイルが DefinitelyTyped でモジュール本体と別に提供されてはおらず、(※1)
- パッケージに同梱されている場合は、
- パッケージのリポジトリに Pull Request を送って取り込んでもらう他ない
修正内容
index.d.ts
- Content の interface を KeyboardAwareScrollViewProperties を extends したものに修正
//追加 import {KeyboardAwareScrollViewProperties} from "react-native-keyboard-aware-scroll-view"; // interface Content { // ↓ 下記のように修正 interface Content extends KeyboardAwareScrollViewProperties {
早速 Pull Request させて頂きました
※1 @type/{パッケージ名}
についてメモ
DefinitelyTyped で対象ライブラリの型定義が提供されている場合
$ yarn add @types/{パッケージ名} --dev
で型定義をライブラリ本体とは別にインストールする
例えば、react-native は DefinitelyTyped/types/react-native/ でライブラリ本体とは別のモジュールとして型定義を提供している
$ yarn add @types/react-native --dev
で react-native の型定義をインストールできる