实践:将现有Vue项目迁移成TypeScript 遇到的骚错误.md
因工作需要,将现有Vue项目中的JS向TS做了迁移,在这个过程中碰到不少坑.就顺带做了笔记.查找资料过程中发现相关错误描述与解决的 中文资料很少.所以在这里分享给大家.其中涉及比较有意思的是:"对象和接口类型的传递"错误,这也是非常耗费我时间的一个错误.
文章目录
迁移方案:
Vue2.9,我目前只想将单独的.js 文件改成.ts,所以做如下配置:
- npm install --save-dev typescript ts-loader
- 加文件:
tsconfig.json
内容:
// tsconfig.json
{
"compilerOptions": {
// 与 Vue 的浏览器支持保持一致
"target": "es5",
// 这可以对 `this` 上的数据属性进行更严格的推断
"strict": true,
// 如果使用 webpack 2+ 或 rollup,可以利用 tree-shake:
"module": "es2015",
"moduleResolution": "node"
}
}
- webpack.config.js修改:
const path = require('path');
module.exports = {
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: [ '.tsx', '.ts', '.js' ]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
- git保存
然后就可以开撸了…记得git保存一下,面对X个TypeScript 找出的错误之前… - 安装 vs-code插件
- TSLint
- TSLint Vue
- 将独立的.js 文件改成 .ts扩展名
TSLint开始提示错误 - 消除所有提示错误
- 编译运行
当然你也可以使用非严格模式(修改 tsconfig.json
“strict”: false,),来降低初期TS的修改困难.虽然不推荐.要搞就搞彻底嘛
配置参考这里:https://www.webpackjs.com/guides/typescript/
遇到错误信息:
Property does not exist on type 'object'
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.
No index signature with a parameter of type 'string' was found on type '{}'.ts(7053)
... ...
…
依靠以下策略解决以上问题:
因为工作需要,将JS项目搞成TS项目.
确实在重构这个过程中,TS的处理,帮我找出项目的至少3个以上的BUG.
是值得的.
对于能从网上容易找到答案的错误,我就没有记录了.
对象初始化
对于向Object中添加任意名字的对象,无法表述:
m_data: object={};
this.xx[ip_key] = value;
解决方案:
m_data: { [key: string]: object };
或者将 读取搞成any:
(this.m_data as any)[ip_key] = value;//不推荐
要小写
核心是: 要使用 小写类型:eg:
number
而不是Number
对于定以一个空对象.希望向其中添加数据,这个时候就是需要声明对象的key,value类型即可:
obj:{[key:string]:number}//key类型为字符串,数据类型为数字.
函数类型
funcA:(source: string, subString: string)=> boolean
funcB:(arg0:object)=>void;
可选参数:
constructor(cbFinished?: (data: object) => void, taskNumber: number = 0){
this.m_cbFinished = cbFinished;
}
cbFinished 是个回调.
那么此时: m_cbFinished的类型为:
cbFinished: ((data: object) => void) | undefined;
即可能是underfined.
总之TS很准确哈哈.
艰难问题解决:用 TS接口 替代 JS抽象父类
问题描述:
当我们需要传递一个类型的时候,而这个类型之前是父类,由于引入了TS的接口
,所以我们用接口替代了父类, 但是报错:
JS代码:
class Father{
}
class Child extends Father{
}
转换后报错的TS代码:
interface IF{
work():void
}
class Child implements Father{
work(): void {}
}
class FM {
m_data: IF; //m_data 是一个类型
constructor() {
//m_data 是一个对象类型
this.m_data = JY; //报错 Type 'typeof JY' is missing the following properties from type 'IF':
}
}
终于解决了:找群里的前辈们一起讨论,最后: ‘’’ ⃢・ ・ ⃢’’'给出了正确答案.
类似问题解决方案我总结为如下三类:
传递类型 用接口做约束时
针对错误: 'IF' only refers to a type, but is being used as a value here.
和 错误: Type 'typeof JY' is missing the following properties from type 'IF':
interface IF {
work(): void;
}
class JY implements IF {
work(): void {}
}
class FM {
m_data: new () => IF;
constructor() {
this.m_data = JY;
}
}
https://stackoverflow.com/questions/39622778/what-is-new-in-typescript
传递对象 用接口做约束时
interface IF {
work(): void;
}
class JY implements IF {
work(): void {}
}
class FM {
m_data: IF;
constructor() {
this.m_data = new JY;
}
}
传递类型 但是不做约束时
针对错误: Type 'typeof JY' is missing the following properties from type 'JY':
class JY {
work(): void { }
}
class FM {
m_data: typeof JY;
constructor() {
this.m_data = JY;
}
}
资料
eg:
interface good{
}
let a : good;
用一些例子.比如 实际 传接口,和不同的接口.
类型参数… …
Typescript告诉你它不知道导入的ResizeObserver可以像类一样实例化,因为这个模块没有提供类型定义。
您可以通过明确声明类型来解决any此问题:
Cannot use ‘new’ with an expression whose type lacks a call or construct signature
解决方案: 参考这里: 关键字是:
construct signature
https://stackoverflow.com/questions/13407036/how-does-interfaces-with-construct-signatures-work
数组类型的写法
两种:
let arr = Array<object>=[{}]
let arr2 = object[]=[{}]
只需要声明一次:
例如 对象声明.TS会通过推导获知所有相关的类型.
除非出现矛盾的时候 才会提醒你.
后记
我通过 错误提示信息 查找的资料基本上Stackoverflow和Github上的.
更多推荐
所有评论(0)