记录一次Typescript类型文件检测的知识学习
相关知识点:typescript,types类型文件,declare module, @lucky-canvas
背景:
公司需要做抽奖的需求,由于咋们项目是taro + react + typescript。于是网上找到抽奖插件@lucky-canvas。
但是@lucky-canvas暴露出来的组件并不是ts写的(其核心的core是用ts写的lucky-canvas)。所以需要为其写类型文件。
在其他组件中使用:
import { LuckyGrid } from '@lucky-canvas/taro/react';
...
...
render () {
...
return (
<View className=''>
<LuckyGrid
...
/>
}
因为该组件不是用typescript写的,所以这样直接使用,ts会报找不到文件。于是我们要写一个声明文件。
因为使用的是: import { LuckyGrid } from '@lucky-canvas/taro/react' 所以我们要使用declare module 来声明一个全局的模块。
declare module '@lucky-canvas/taro/react' {
}
到这了以后点击 import { LuckyGrid } from '@lucky-canvas/taro/react' 这句from后面的的语句就可以跳过来了。
于是定义一个LuckyGrid的类型的组件:
import React from 'react'
declare module '@lucky-canvas/taro/react' {
type LuckyGrid = React.ComponentClass<{...}>;
}
这么写会发现一个报错: 扩大中的模块名称无效。模块“@lucky-canvas/taro/react”解析到位于“/Users/edy/Desktop/work/miyuan-front-projects/node_modules/@lucky-canvas/taro/react/index.js”处的非类型化模块,其无法扩大。 然后问了下部门大佬,他的解释是: 不能直接import, 有import和export就成内部模块了,现在是要定义一个全局模块. 于是写法改成了下面:
declare module '@lucky-canvas/taro/react' {
type LuckyGrid = import('react').ComponentClass<{...}>;
}
这样写不会报错了。
但是在使用的时候发现又报错了:
“LuckyGrid”仅表示类型,但在此处却作为值使用。
所以作为值使用的话要使用export 和 const 作为值使用
于是写成下面这样;
declare module '@lucky-canvas/taro/react' { // TODO
type LuckyGrid = import('react').ComponentClass<{}>;
const luckyCanvas: Tmp;
interface Tmp {
LuckyGrid: LuckyGrid,
}
export = luckyCanvas;
}
这样就可以了。
总结如何声明一个非typescript写的组件写声明文件:
- 使用declare module 'xxx'来声明全局模块,xxx表示引入该模块的路径
- 不要使用export,import 静态属性,使用import()动态语言。
- 使用export 结合 const 来使用值类型