10分钟学习一次Typescript类型文件检测的知识

1,125 阅读2分钟

记录一次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写的组件写声明文件:

  1. 使用declare module 'xxx'来声明全局模块,xxx表示引入该模块的路径
  2. 不要使用export,import 静态属性,使用import()动态语言。
  3. 使用export 结合 const 来使用值类型