接上一篇《react-native 为本地js和开源库的js编写.d.ts声明文件》,本篇分析为在react-native中应用js文件,我是如何写声明文件 *.d.ts
的。
在学习Typescript时,关于如何编写声明文件。文档中提到,可参考、学习开源库中的源码声明。因此,源码中必然能给我们代码更大实践效果上的收获!
编写声明文件灵感分析从两个方面:
1,源码分析,
node-modules/@Types/react-native
是如何编写声明全局变量;
2,源码分析,node-modules/react-native-ui-lib
是如何编写声明文件的;
3,实操分析,对本地自己个写的js代码,是如何编写声明文件的;
分析源码node-modules/@Types/react-native
打开源码目录 [node-moduels/@Types/react-native](https://github.com/wix/react-native-ui-lib)
,结合react-native的编码习惯。可以发现 index.d.ts
必定是最终面向开发者使用的声明文件了。
// index.d.ts
...
... 代码省略...
...
//
// Prop Types
//
export const ColorPropType: React.Validator<string>;
export const EdgeInsetsPropType: React.Validator<Insets>;
export const PointPropType: React.Validator<PointPropType>;
export const ViewPropTypes: React.ValidationMap<ViewProps>;
declare global {
interface NodeRequire {
(id: string): any;
}
var require: NodeRequire;
/**
* Console polyfill
* @see https://facebook.github.io/react-native/docs/javascript-environment.html#polyfills
*/
interface Console {
error(message?: any, ...optionalParams: any[]): void;
info(message?: any, ...optionalParams: any[]): void;
log(message?: any, ...optionalParams: any[]): void;
warn(message?: any, ...optionalParams: any[]): void;
trace(message?: any, ...optionalParams: any[]): void;
debug(message?: any, ...optionalParams: any[]): void;
table(...data: any[]): void;
groupCollapsed(label?: string): void;
groupEnd(): void;
group(label?: string): void;
disableYellowBox: boolean;
ignoredYellowBox: string[];
}
var console: Console;
/**
* This contains the non-native `XMLHttpRequest` object, which you can use if you want to route network requests
* through DevTools (to trace them):
*
* global.XMLHttpRequest = global.originalXMLHttpRequest;
*
* @see https://github.com/facebook/react-native/issues/934
*/
const originalXMLHttpRequest: any;
const __BUNDLE_START_TIME__: number;
const ErrorUtils: ErrorUtils;
/**
* This variable is set to true when react-native is running in Dev mode
* Typical usage:
* <code> if (__DEV__) console.log('Running in dev mode')</code>
*/
const __DEV__: boolean;
const HermesInternal: null | {
};
}
然后则会发现声明全局对象的 declare global {}
。结合我们平时使用过程中有用到打印日志的方法console.log('这里打印日志 - 声明:全局对象-全局变量')
。可以确定console
是已被声明的全局变量。那么我们个人应该怎么通过·global·
扩展自己个的全局变量。
当然扩展全局变量,在Typescript这门技术语言中是有自己的一套系统定义的。中文文档有说道,在 npm 包或 UMD 库中扩展全局变量的方式。 而通过实践对比来看,在react-native中要对全局进行扩展变量和npm 包或 UMD 库中扩展全局变量的方式是一致的。如在这里对全局变量进行扩展,通过 —— declare global
// */namesp/index.d.ts
//
// Prop Types
//
export {
};
declare global {
var gHeight: string | number;
var gWidth: string | number;
}
如果 注释掉这行代码 export {};
会有什么变化?export {};
是做什么用的?
会发现有错误提示:Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.ts(2669)
[全局作用域的扩展只能直接嵌套在外部模块或环境模块声明中。ts(2669)]
外部模块的声明方式则是 export
方式。内部模块的声明方式是namespace
方式。所以是提示我们在当前的index.d.ts声明文件
中进行全局作用域的扩展,要以 export
方式进行声明使得index.d.ts声明文件
的作用域成为外部模块。[用来告诉编译器这是一个模块的声明文件,而不是一个全局变量的声明文件。]
分析源码node-modules/react-native-ui-lib
声明文件的内容依照什么编写?
截图展示开源库react-native-ui-lib的目录结构。
其中图中看到 index.d.ts
是为该开源库所做的声明文件的总的对外输出。沿着这条线索追踪 ~ 选择export * from './components';
进入可看到声明文件 *\components\index.d.ts
// */node_modules/react-native-ui-lib/typings/components/index.d.ts
export * from './ActionBar';
export * from './ActionSheet';
export * from './Avatar';
export * from './Badge';
export * from './Button';
export * from './Card';
... ...
export * from './Text';
export * from './Toast';
export * from './TouchableOpacity';
export * from './Tour';
export * from './View';
export * from './WheelPickerDialog';
在此选择较熟悉的组件 export * from './Toast';
进入看源码
// */node_modules/react-native-ui-lib/typings/components/Toast.d.ts
import {
ReactElement} from 'react';
import {
GestureResponderEvent,
ImageRequireSource,
StyleProp,
TextStyle
} from 'react-native';
import {
BaseComponent} from '../commons';
import {
ColorValue} from '../style/colors';
import {
ButtonProps} from './Button';
import {
BlurViewProperties} from '@react-native-community/blur';
export type ToastPosition = "relative" | "top" | "bottom";
export interface ToastProps {
visible?: boolean;
position?: ToastPosition;
height?: number;
backgroundColor?: ColorValue;
color?: ColorValue;
message?: string;
messageStyle?: StyleProp<TextStyle>;
icon?: ImageRequireSource;
actions?: ReadonlyArray<ButtonProps>;
onDismiss?: (event: GestureResponderEvent) => void;
autoDismiss?: number;
allowDismiss?: boolean;
onAnimationEnd?: (visible: boolean) => void;
renderContent?: (props: ToastProps)