记一次Typescript改造

127 阅读2分钟

项目说明

node项目,运行环境为服务端。使用commonjs规范编写。

将js文件改为ts文件

find ./src -name "*.js" | sed 's/.js//' | xargs -n1 -I {} mv {}.js {}.ts

问题记录

  • Cannot find name 'require'

image.png

按提示安装依赖即可

npm i --save-dev @types/node
  • commonjs写法问题

由于TS只认ESM规范模块,遵循commonjs规范的代码会认为是一个全局运行代码,导致TS校验报错,但是不影响编译后运行。

image.png

解决方案: 1. 在页面添加 export {},让ts识别为一个模块; 2. 改为ESM规范;

  • 如何声明第三方库类型

以koa为例,首先要安装koa的type:

npm i --save-dev @type/koa

然后顺藤摸瓜,首先从入口文件入手,这里可以确定middleware的类型为:Application.Middleware<StateT & NewStateT, ContextT & NewContextT>

image.png 进一步跟踪:

type Middleware<StateT = DefaultState, ContextT = DefaultContext, ResponseBodyT = any> = compose.Middleware<
        ParameterizedContext<StateT, ContextT, ResponseBodyT>
    >;
    
type Middleware<T> = (context: T, next: Koa.Next) => any;

type ParameterizedContext<StateT = DefaultState, ContextT = DefaultContext, ResponseBodyT = unknown> = ExtendableContext
        & { state: StateT; }
        & ContextT
        & { body: ResponseBodyT; response: { body: ResponseBodyT }; 
};

将其中的泛型用实际类型替换后得到

type Middleware = (context: ExtendableContext
        & { state: DefaultState; }
        & DefaultContext
        & { body: any; response: { body: any }, next: Koa.Next) => any;
  • 全局类型声明

  1. 首先在tsconfig.json中配置typesRoot,包含放置类型声明文件的目录,其中"./node_modules/@types"是默认值,不能漏了
"typeRoots": [
      "./typing",
      "./node_modules/@types"
]
  1. 在typing目录下新建子目录(很关键),目录名随意
  2. 在子目录下新建index.d.ts文件(不能改名)
  3. 类型文件不能使用ESM预发,不然就不能作为全局变量声明了
  4. 如果依赖其他类型声明文件,可以使用三斜杠命令,前提是依赖的类型什么文件也是全局声明的,否则无效(如@types/node)
  5. 如果没生效,试试重启IDC(坑)
  • try catch 的error对象类型为unknown,导致读取error信息时报错

参考Stack Overflow的回答 stackoverflow.com/questions/6… 设置useUnknownInCatchVariables属性为false即可

参考文章

  1. # esModuleInterop 到底做了什么?
  2. Typescript modules 定义