- お世話になっているライブラリ 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 の型定義をインストールできる