竹林樱草 发表于 2023-4-10 13:19:38

OpenTiny 跨端、跨框架组件库升级TypeScript,10万行代码重获新生

摘要:一份精心准备的《JS项目改造TS指南》文档供大家参考,顺便介绍TS<template>
<input ref="el" />
</template>基础知识和<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>在<template>
<input ref="el" />
</template>Vue<template>
<input ref="el" />
</template>中的实践。本文分享自华为云社区《历史性的时刻!OpenTiny<template>
<input ref="el" />
</template>跨端、跨框架组件库正式升级<template>
<input ref="el" />
</template>TypeScript,10<template>
<input ref="el" />
</template>万行代码重获新生!》,作者:Kagol。
根据<template>
<input ref="el" />
</template>The<template>
<input ref="el" />
</template>Software<template>
<input ref="el" />
</template>House<template>
<input ref="el" />
</template>发布的《2022<template>
<input ref="el" />
</template>前端开发市场状态调查报告》数据显示,使用<template>
<input ref="el" />
</template>TypeScript<template>
<input ref="el" />
</template>的人数已经达到<template>
<input ref="el" />
</template>84%,和<template>
<input ref="el" />
</template>2021<template>
<input ref="el" />
</template>年相比增加了<template>
<input ref="el" />
</template>7<template>
<input ref="el" />
</template>个百分点。
3月16日发布了<template>
<input ref="el" />
</template>TypeScript<template>
<input ref="el" />
</template>5.0<template>
<input ref="el" />
</template>版本。TypeScript<template>
<input ref="el" />
</template>可谓逐年火热,使用者呈现逐年上升的趋势,再不学起来就说不过去。
我们<template>
<input ref="el" />
</template>OpenTiny<template>
<input ref="el" />
</template>近期做了一次大的升级,将原来运行了<template>
<input ref="el" />
</template>9年<template>
<input ref="el" />
</template>的<template>
<input ref="el" />
</template>JavaScript<template>
<input ref="el" />
</template>代码升级到了<template>
<input ref="el" />
</template>TypeScript,并通过<template>
<input ref="el" />
</template>Monorepo<template>
<input ref="el" />
</template>进行子包的管理,还在用<template>
<input ref="el" />
</template>JavaScript<template>
<input ref="el" />
</template>的朋友抓紧升级哦,我特意准备了一份《JS项目改造TS指南》文档供大家参考,顺便介绍了一些<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>基础知识和<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>在<template>
<input ref="el" />
</template>Vue<template>
<input ref="el" />
</template>中的一些实践。
通过本文你将收获:

[*]通过了解<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>的四大好处,说服自己下定决心学习<template>
<input ref="el" />
</template>TS
[*]5<template>
<input ref="el" />
</template>分钟学习<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>最基础和常用的知识点,快速入门,包教包会
[*]了解如何在<template>
<input ref="el" />
</template>Vue<template>
<input ref="el" />
</template>中使用<template>
<input ref="el" />
</template>TypeScript,给<template>
<input ref="el" />
</template>Vue2<template>
<input ref="el" />
</template>开发者切换到<template>
<input ref="el" />
</template>Vue3<template>
<input ref="el" />
</template>+<template>
<input ref="el" />
</template>TypeScript<template>
<input ref="el" />
</template>提供最基本的参考
[*]如何将现有的<template>
<input ref="el" />
</template>JS<template>
<input ref="el" />
</template>项目改造成<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>项目
1<template>
<input ref="el" />
</template>学习<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>的好处

1.1<template>
<input ref="el" />
</template>好处一:紧跟潮流:让自己看起来很酷

如果你没学过<template>
<input ref="el" />
</template>TS
你的前端朋友:都<template>
<input ref="el" />
</template>2023<template>
<input ref="el" />
</template>年了,你还不会<template>
<input ref="el" />
</template>TS?给你一个眼色你自己感悟吧
如果你学过<template>
<input ref="el" />
</template>TS
你的前端朋友:哇,你们的项目已经用上<template>
<input ref="el" />
</template>Vue3<template>
<input ref="el" />
</template>+<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>啦,看起来真棒!教教我吧
如果说上面那个好处太虚了,那下面的3条好处可都是实实在在能让自己受益的。
1.2<template>
<input ref="el" />
</template>好处二:智能提示:提升开发者体验和效率

当循环一个对象数组时,对象的属性列表可以直接显示出来,不用到对象的定义中去查询该对象有哪些属性。
通过调用后台接口获取的异步数据也可以通过TS类型进行智能提示,这样相当于集成了接口文档,后续后台修改字段,我们很容易就能发现。
Vue<template>
<input ref="el" />
</template>组件的属性和事件都可以智能提示。
下图是我们OpenTiny跨端跨框架前端组件库中的<template>
<input ref="el" />
</template>Alert<template>
<input ref="el" />
</template>组件,当在组件标签中输入<template>
<input ref="el" />
</template>des<template>
<input ref="el" />
</template>时,会自动提示<template>
<input ref="el" />
</template>description<template>
<input ref="el" />
</template>属性;当输入<template>
<input ref="el" />
</template>@c<template>
<input ref="el" />
</template>时,会自动提示<template>
<input ref="el" />
</template>@close<template>
<input ref="el" />
</template>事件。
1.3<template>
<input ref="el" />
</template>好处三:错误标记:代码哪里有问题一眼就知道

在<template>
<input ref="el" />
</template>JS<template>
<input ref="el" />
</template>项目使用不存在的对象属性,在编码阶段不容易看出来,到运行时才会报错。
在<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>项目使用不存在的对象属性,在IDE中会有红色波浪线标记,鼠标移上去能看到具体的错误信息。
在<template>
<input ref="el" />
</template>JS<template>
<input ref="el" />
</template>项目,调用方法时拼错单词不容易被发现,要在运行时才会将错误暴露出来。
在<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>项目会有红色波浪线提示,一眼就看出拼错单词。
1.4<template>
<input ref="el" />
</template>好处四:类型约束:用我的代码就得听我的

你写了一个工具函数<template>
<input ref="el" />
</template>getType<template>
<input ref="el" />
</template>给别人用,限定参数只能是指定的字符串,这时如果使用这个函数的人传入其他字符串,就会有红色波浪线提示。
Vue<template>
<input ref="el" />
</template>组件也是一样的,可以限定组件<template>
<input ref="el" />
</template>props<template>
<input ref="el" />
</template>的类型,组件的使用者如果传入不正确的类型,将会有错误提示,比如:我们<template>
<input ref="el" />
</template>OpenTiny<template>
<input ref="el" />
</template>的<template>
<input ref="el" />
</template>Alert<template>
<input ref="el" />
</template>组件,closable<template>
<input ref="el" />
</template>只能传入<template>
<input ref="el" />
</template>Boolean<template>
<input ref="el" />
</template>值,如果传入一个字符串就会有错误提示。
2<template>
<input ref="el" />
</template>极简<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>基础,5分钟学会

以下内容虽然不多,但包含了实际项目开发中最实用的部分,对于<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>入门者来说也是能很快学会的,学不会的找我,手把手教,包教包会,有手就会写。
2.1<template>
<input ref="el" />
</template>基本类型

用得较多的类型就下面5个,更多类型请参考:TS官网文档

[*]布尔<template>
<input ref="el" />
</template>boolean
[*]数值<template>
<input ref="el" />
</template>number
[*]字符串<template>
<input ref="el" />
</template>string
[*]空值<template>
<input ref="el" />
</template>void:表示没有任何返回值的函数
[*]任意<template>
<input ref="el" />
</template>any:表示不被类型检查
用法也很简单:
let<template>
<input ref="el" />
</template>isDone:<template>
<input ref="el" />
</template>boolean<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>false;
let<template>
<input ref="el" />
</template>myFavoriteNumber:<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>6;
let<template>
<input ref="el" />
</template>myName:<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>'Kagol';
function<template>
<input ref="el" />
</template>alertName(name:<template>
<input ref="el" />
</template>string):<template>
<input ref="el" />
</template>void<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>
<template>
<input ref="el" />
</template>console.log(`My<template>
<input ref="el" />
</template>name<template>
<input ref="el" />
</template>is<template>
<input ref="el" />
</template>${name}`);<template>
<input ref="el" />
</template>
}默认情况下,name<template>
<input ref="el" />
</template>会自动类型推导成<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>类型,此时如果给它赋值为一个<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>类型的值,会出现错误提示。
let<template>
<input ref="el" />
</template>name<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>'Kagol'<template>
<input ref="el" />
</template>
name<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>6如果给<template>
<input ref="el" />
</template>name<template>
<input ref="el" />
</template>设置<template>
<input ref="el" />
</template>any<template>
<input ref="el" />
</template>类型,表示不做类型检查,这时错误提示消失。
let<template>
<input ref="el" />
</template>name:<template>
<input ref="el" />
</template>any<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>'Kagol'<template>
<input ref="el" />
</template>
name<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>62.2<template>
<input ref="el" />
</template>函数

主要定义函数参数和返回值类型。
看一下例子:
const<template>
<input ref="el" />
</template>sum<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>(x:<template>
<input ref="el" />
</template>number,<template>
<input ref="el" />
</template>y:<template>
<input ref="el" />
</template>number):<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>x<template>
<input ref="el" />
</template>+<template>
<input ref="el" />
</template>y<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>
}以上代码包含以下<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>校验规则:

[*]调用<template>
<input ref="el" />
</template>sum<template>
<input ref="el" />
</template>函数时,必须传入两个参数,多一个或者少一个都不行
[*]并且这两个参数的类型要为<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>类型
[*]且函数的返回值为<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>类型
少参数:
多参数:
参数类型错误:
返回值:
用问号<template>
<input ref="el" />
</template>?<template>
<input ref="el" />
</template>可以表示该参数是可选的。
const<template>
<input ref="el" />
</template>sum<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>(x:<template>
<input ref="el" />
</template>number,<template>
<input ref="el" />
</template>y?:<template>
<input ref="el" />
</template>number):<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>x<template>
<input ref="el" />
</template>+<template>
<input ref="el" />
</template>(y<template>
<input ref="el" />
</template>||<template>
<input ref="el" />
</template>0);<template>
<input ref="el" />
</template>
}<template>
<input ref="el" />
</template>
sum(1)<template>
<input ref="el" />
</template>如果将<template>
<input ref="el" />
</template>y<template>
<input ref="el" />
</template>定义为可选参数,则调用<template>
<input ref="el" />
</template>sum<template>
<input ref="el" />
</template>函数时可以只传入一个参数。
需要注意的是,可选参数必须接在必需参数后面。换句话说,可选参数后面不允许再出现必需参数了。
给<template>
<input ref="el" />
</template>y<template>
<input ref="el" />
</template>增加默认值<template>
<input ref="el" />
</template>0<template>
<input ref="el" />
</template>之后,y<template>
<input ref="el" />
</template>会自动类型推导成<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>类型,不需要加<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>类型,并且由于有默认值,也不需要加可选参数。
const<template>
<input ref="el" />
</template>sum<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>(x:<template>
<input ref="el" />
</template>number,<template>
<input ref="el" />
</template>y<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>0):<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>x<template>
<input ref="el" />
</template>+<template>
<input ref="el" />
</template>y<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>
}
sum(1)<template>
<input ref="el" />
</template>
sum(1,<template>
<input ref="el" />
</template>2)<template>
<input ref="el" />
</template>2.3<template>
<input ref="el" />
</template>数组

数组类型有两种表示方式:

[*]类型<template>
<input ref="el" />
</template>+<template>
<input ref="el" />
</template>方括号<template>
<input ref="el" />
</template>表示法
[*]泛型<template>
<input ref="el" />
</template>表示法
//<template>
<input ref="el" />
</template>`类型<template>
<input ref="el" />
</template>+<template>
<input ref="el" />
</template>方括号`<template>
<input ref="el" />
</template>表示法
let<template>
<input ref="el" />
</template>fibonacci:<template>
<input ref="el" />
</template>number[]<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>[1,<template>
<input ref="el" />
</template>1,<template>
<input ref="el" />
</template>2,<template>
<input ref="el" />
</template>3,<template>
<input ref="el" />
</template>5]
//<template>
<input ref="el" />
</template>泛型表示法
let<template>
<input ref="el" />
</template>fibonacci:<template>
<input ref="el" />
</template>Array<number><template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>[1,<template>
<input ref="el" />
</template>1,<template>
<input ref="el" />
</template>2,<template>
<input ref="el" />
</template>3,<template>
<input ref="el" />
</template>5]这两种都可以表示数组类型,看自己喜好进行选择即可。
如果是类数组,则不可以用数组的方式定义类型,因为它不是真的数组,需要用<template>
<input ref="el" />
</template>interface<template>
<input ref="el" />
</template>进行定义
interface<template>
<input ref="el" />
</template>IArguments<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>[index:<template>
<input ref="el" />
</template>number]:<template>
<input ref="el" />
</template>any;
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>length:<template>
<input ref="el" />
</template>number;
<template>
<input ref="el" />
</template>callee:<template>
<input ref="el" />
</template>Function;
}
function<template>
<input ref="el" />
</template>sum()<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>let<template>
<input ref="el" />
</template>args:<template>
<input ref="el" />
</template>IArguments<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>arguments
}IArguments<template>
<input ref="el" />
</template>类型已在<template>
<input ref="el" />
</template>TypeScript<template>
<input ref="el" />
</template>中内置,类似的还有很多:
let<template>
<input ref="el" />
</template>body:<template>
<input ref="el" />
</template>HTMLElement<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>document.body;
let<template>
<input ref="el" />
</template>allDiv:<template>
<input ref="el" />
</template>NodeList<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>document.querySelectorAll('div');
document.addEventListener('click',<template>
<input ref="el" />
</template>function(e:<template>
<input ref="el" />
</template>MouseEvent)<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>//<template>
<input ref="el" />
</template>Do<template>
<input ref="el" />
</template>something
});如果数组里的元素类型并不都是相同的怎么办呢?
这时<template>
<input ref="el" />
</template>any<template>
<input ref="el" />
</template>类型就发挥作用啦啦
let<template>
<input ref="el" />
</template>list:<template>
<input ref="el" />
</template>any[]<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>['OpenTiny',<template>
<input ref="el" />
</template>112,<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>website:<template>
<input ref="el" />
</template>'https://opentiny.design/'<template>
<input ref="el" />
</template>}];2.4<template>
<input ref="el" />
</template>接口

接口简单理解就是一个对象的“轮廓”
interface<template>
<input ref="el" />
</template>IResourceItem<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>name:<template>
<input ref="el" />
</template>string;
<template>
<input ref="el" />
</template>value?:<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number;
<template>
<input ref="el" />
</template>total?:<template>
<input ref="el" />
</template>number;
<template>
<input ref="el" />
</template>checked?:<template>
<input ref="el" />
</template>boolean;
}接口是可以继承接口的
interface<template>
<input ref="el" />
</template>IClosableResourceItem<template>
<input ref="el" />
</template>extends<template>
<input ref="el" />
</template>IResourceItem<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>closable?:<template>
<input ref="el" />
</template>boolean;
}这样<template>
<input ref="el" />
</template>IClosableResourceItem<template>
<input ref="el" />
</template>就包含了<template>
<input ref="el" />
</template>IResourceItem<template>
<input ref="el" />
</template>属性和自己的<template>
<input ref="el" />
</template>closable<template>
<input ref="el" />
</template>可选属性。
接口也是可以被类实现的
interface<template>
<input ref="el" />
</template>Alarm<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>alert():<template>
<input ref="el" />
</template>void;
}
class<template>
<input ref="el" />
</template>Door<template>
<input ref="el" />
</template>{
}
class<template>
<input ref="el" />
</template>SecurityDoor<template>
<input ref="el" />
</template>extends<template>
<input ref="el" />
</template>Door<template>
<input ref="el" />
</template>implements<template>
<input ref="el" />
</template>Alarm<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>alert()<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>console.log('SecurityDoor<template>
<input ref="el" />
</template>alert')
<template>
<input ref="el" />
</template>}
}如果类实现了一个接口,却不写具体的实现代码,则会有错误提示
2.5<template>
<input ref="el" />
</template>联合类型<template>
<input ref="el" />
</template>&<template>
<input ref="el" />
</template>类型别名

联合类型是指取值可以为多种类型中的一种,而类型别名常用于联合类型。
看以下例子:
//<template>
<input ref="el" />
</template>联合类型
let<template>
<input ref="el" />
</template>myFavoriteNumber:<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number
myFavoriteNumber<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>'six'
myFavoriteNumber<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>6
//<template>
<input ref="el" />
</template>类型别名
type<template>
<input ref="el" />
</template>FavoriteNumber<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number
let<template>
<input ref="el" />
</template>myFavoriteNumber:<template>
<input ref="el" />
</template>FavoriteNumber当<template>
<input ref="el" />
</template>TypeScript<template>
<input ref="el" />
</template>不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
function<template>
<input ref="el" />
</template>getLength(something:<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number):<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>something.length
}
//<template>
<input ref="el" />
</template>index.ts(2,22):<template>
<input ref="el" />
</template>error<template>
<input ref="el" />
</template>TS2339:<template>
<input ref="el" />
</template>Property<template>
<input ref="el" />
</template>'length'<template>
<input ref="el" />
</template>does<template>
<input ref="el" />
</template>not<template>
<input ref="el" />
</template>exist<template>
<input ref="el" />
</template>on<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>'string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number'.
//<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>Property<template>
<input ref="el" />
</template>'length'<template>
<input ref="el" />
</template>does<template>
<input ref="el" />
</template>not<template>
<input ref="el" />
</template>exist<template>
<input ref="el" />
</template>on<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>'number'.
上例中,length<template>
<input ref="el" />
</template>不是<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>和<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>的共有属性,所以会报错。
访问<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>和<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>的共有属性是没问题的:
function<template>
<input ref="el" />
</template>getString(something:<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number):<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>something.toString()
}2.6<template>
<input ref="el" />
</template>类型断言

类型断言(Type<template>
<input ref="el" />
</template>Assertion)可以用来手动指定一个值的类型。
语法:值<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>类型,比如:(animal<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>Fish).swim()
类型断言主要有以下用途:

[*]将一个联合类型断言为其中一个类型
[*]将一个父类断言为更加具体的子类
[*]将任何一个类型断言为<template>
<input ref="el" />
</template>any
[*]将<template>
<input ref="el" />
</template>any<template>
<input ref="el" />
</template>断言为一个具体的类型
我们一个个来看。
用途1:将一个联合类型断言为其中一个类型
interface<template>
<input ref="el" />
</template>Cat<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>name:<template>
<input ref="el" />
</template>string;
<template>
<input ref="el" />
</template>run():<template>
<input ref="el" />
</template>void;
}
interface<template>
<input ref="el" />
</template>Fish<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>name:<template>
<input ref="el" />
</template>string;
<template>
<input ref="el" />
</template>swim():<template>
<input ref="el" />
</template>void;
}
const<template>
<input ref="el" />
</template>animal:<template>
<input ref="el" />
</template>Cat<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>Fish<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>new<template>
<input ref="el" />
</template>Animal()
animal.swim()animal<template>
<input ref="el" />
</template>是一个联合类型,可能是猫<template>
<input ref="el" />
</template>Cat,也可能是鱼<template>
<input ref="el" />
</template>Fish,如果直接调用<template>
<input ref="el" />
</template>swim<template>
<input ref="el" />
</template>方法是要出现错误提示的,因为猫不会游泳。
这时类型断言就派上用场啦啦,因为调用的是<template>
<input ref="el" />
</template>swim<template>
<input ref="el" />
</template>方法,那肯定是鱼,所以直接断言为<template>
<input ref="el" />
</template>Fish<template>
<input ref="el" />
</template>就不会出现错误提示。
const<template>
<input ref="el" />
</template>animal:<template>
<input ref="el" />
</template>Cat<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>Fish<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>new<template>
<input ref="el" />
</template>Animal()
(animal<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>Fish).swim()用途2:将一个父类断言为更加具体的子类
class<template>
<input ref="el" />
</template>ApiError<template>
<input ref="el" />
</template>extends<template>
<input ref="el" />
</template>Error<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>code:<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>0;
}
class<template>
<input ref="el" />
</template>HttpError<template>
<input ref="el" />
</template>extends<template>
<input ref="el" />
</template>Error<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>statusCode:<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>200;
}
function<template>
<input ref="el" />
</template>isApiError(error:<template>
<input ref="el" />
</template>Error)<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>if<template>
<input ref="el" />
</template>(typeof<template>
<input ref="el" />
</template>(error<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>ApiError).code<template>
<input ref="el" />
</template>===<template>
<input ref="el" />
</template>'number')<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>true;
<template>
<input ref="el" />
</template>}
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>false;
}ApiError<template>
<input ref="el" />
</template>和<template>
<input ref="el" />
</template>HttpError<template>
<input ref="el" />
</template>都继承自<template>
<input ref="el" />
</template>Error<template>
<input ref="el" />
</template>父类,error<template>
<input ref="el" />
</template>变量的类型是<template>
<input ref="el" />
</template>Error,去取<template>
<input ref="el" />
</template>code<template>
<input ref="el" />
</template>变量肯定是不行,因为取的是<template>
<input ref="el" />
</template>code<template>
<input ref="el" />
</template>变量,我们可以直接断言为<template>
<input ref="el" />
</template>ApiError<template>
<input ref="el" />
</template>类型。
用途3:将任何一个类型断言为<template>
<input ref="el" />
</template>any
这个非常有用,看一下例子:
function<template>
<input ref="el" />
</template>getCacheData(key:<template>
<input ref="el" />
</template>string):<template>
<input ref="el" />
</template>any<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>(window<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>any).cache;
}
interface<template>
<input ref="el" />
</template>Cat<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>name:<template>
<input ref="el" />
</template>string;
<template>
<input ref="el" />
</template>run():<template>
<input ref="el" />
</template>void;
}
const<template>
<input ref="el" />
</template>tom<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>getCacheData('tom')<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>Cat;getCacheData<template>
<input ref="el" />
</template>是一个历史遗留函数,不是你写的,由于他返回<template>
<input ref="el" />
</template>any<template>
<input ref="el" />
</template>类型,就等于放弃了<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>的类型检验,假如<template>
<input ref="el" />
</template>tom<template>
<input ref="el" />
</template>是一只猫,里面有<template>
<input ref="el" />
</template>name<template>
<input ref="el" />
</template>属性和<template>
<input ref="el" />
</template>run()<template>
<input ref="el" />
</template>方法,但由于返回<template>
<input ref="el" />
</template>any<template>
<input ref="el" />
</template>类型,tom.<template>
<input ref="el" />
</template>是没有任何提示的。
如果将其断言为<template>
<input ref="el" />
</template>Cat<template>
<input ref="el" />
</template>类型,就可以<template>
<input ref="el" />
</template>点<template>
<input ref="el" />
</template>出<template>
<input ref="el" />
</template>name<template>
<input ref="el" />
</template>属性和<template>
<input ref="el" />
</template>run()<template>
<input ref="el" />
</template>方法。
用途4:将<template>
<input ref="el" />
</template>any<template>
<input ref="el" />
</template>断言为一个具体的类型
这个比较常见的场景是给<template>
<input ref="el" />
</template>window<template>
<input ref="el" />
</template>挂在一个自己的变量和方法。
window.foo<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>1;
//<template>
<input ref="el" />
</template>index.ts:1:8<template>
<input ref="el" />
</template>-<template>
<input ref="el" />
</template>error<template>
<input ref="el" />
</template>TS2339:<template>
<input ref="el" />
</template>Property<template>
<input ref="el" />
</template>'foo'<template>
<input ref="el" />
</template>does<template>
<input ref="el" />
</template>not<template>
<input ref="el" />
</template>exist<template>
<input ref="el" />
</template>on<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>'Window<template>
<input ref="el" />
</template>&<template>
<input ref="el" />
</template>typeof<template>
<input ref="el" />
</template>globalThis'.
(window<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>any).foo<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>1;由于<template>
<input ref="el" />
</template>window<template>
<input ref="el" />
</template>下没有<template>
<input ref="el" />
</template>foo<template>
<input ref="el" />
</template>变量,直接赋值会有错误提示,将<template>
<input ref="el" />
</template>window<template>
<input ref="el" />
</template>断言为<template>
<input ref="el" />
</template>any<template>
<input ref="el" />
</template>就没问题啦啦。
2.7<template>
<input ref="el" />
</template>元组

数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象。
let<template>
<input ref="el" />
</template>tom:<template>
<input ref="el" />
</template>[string,<template>
<input ref="el" />
</template>number]<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>['Tom',<template>
<input ref="el" />
</template>25];给元组类型赋值时,数组每一项的类型需要和元组定义的类型对应上。
当赋值或访问一个已知索引的元素时,会得到正确的类型:
let<template>
<input ref="el" />
</template>tom:<template>
<input ref="el" />
</template>[string,<template>
<input ref="el" />
</template>number];
tom<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>'Tom';
tom<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>25;
tom.slice(1);
tom.toFixed(2);也可以只赋值其中一项:
let<template>
<input ref="el" />
</template>tom:<template>
<input ref="el" />
</template>[string,<template>
<input ref="el" />
</template>number];
tom<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>'Tom';但是当直接对元组类型的变量进行初始化或者赋值的时候,需要提供所有元组类型中指定的项。
let<template>
<input ref="el" />
</template>tom:<template>
<input ref="el" />
</template>[string,<template>
<input ref="el" />
</template>number];
tom<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>['Tom'];
//<template>
<input ref="el" />
</template>Property<template>
<input ref="el" />
</template>'1'<template>
<input ref="el" />
</template>is<template>
<input ref="el" />
</template>missing<template>
<input ref="el" />
</template>in<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>''<template>
<input ref="el" />
</template>but<template>
<input ref="el" />
</template>required<template>
<input ref="el" />
</template>in<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>'[string,<template>
<input ref="el" />
</template>number]'.当添加越界的元素时,它的类型会被限制为元组中每个类型的联合类型:
let<template>
<input ref="el" />
</template>tom:<template>
<input ref="el" />
</template>[string,<template>
<input ref="el" />
</template>number];
tom<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>['Tom',<template>
<input ref="el" />
</template>25];
tom.push('male');
tom.push(true);
//<template>
<input ref="el" />
</template>Argument<template>
<input ref="el" />
</template>of<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>'true'<template>
<input ref="el" />
</template>is<template>
<input ref="el" />
</template>not<template>
<input ref="el" />
</template>assignable<template>
<input ref="el" />
</template>to<template>
<input ref="el" />
</template>parameter<template>
<input ref="el" />
</template>of<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>'string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number'.push<template>
<input ref="el" />
</template>字符串和数字都可以,布尔就不行。
2.8<template>
<input ref="el" />
</template>枚举

枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天,颜色限定为红绿蓝等。
enum<template>
<input ref="el" />
</template>Days<template>
<input ref="el" />
</template>{Sun,<template>
<input ref="el" />
</template>Mon,<template>
<input ref="el" />
</template>Tue,<template>
<input ref="el" />
</template>Wed,<template>
<input ref="el" />
</template>Thu,<template>
<input ref="el" />
</template>Fri,<template>
<input ref="el" />
</template>Sat}枚举成员会被赋值为从<template>
<input ref="el" />
</template>0<template>
<input ref="el" />
</template>开始递增的数字,同时也会对枚举值到枚举名进行反向映射:
console.log(Days.Sun<template>
<input ref="el" />
</template>===<template>
<input ref="el" />
</template>0)<template>
<input ref="el" />
</template>//<template>
<input ref="el" />
</template>true
console.log(Days<template>
<input ref="el" />
</template>===<template>
<input ref="el" />
</template>'Sun')<template>
<input ref="el" />
</template>//<template>
<input ref="el" />
</template>true
console.log('Days',<template>
<input ref="el" />
</template>Days)手动赋值:未手动赋值的枚举项会接着上一个枚举项递增。
enum<template>
<input ref="el" />
</template>Days<template>
<input ref="el" />
</template>{Sun<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>7,<template>
<input ref="el" />
</template>Mon<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>1,<template>
<input ref="el" />
</template>Tue,<template>
<input ref="el" />
</template>Wed,<template>
<input ref="el" />
</template>Thu,<template>
<input ref="el" />
</template>Fri,<template>
<input ref="el" />
</template>Sat}2.9<template>
<input ref="el" />
</template>类

给类加上<template>
<input ref="el" />
</template>TypeScript<template>
<input ref="el" />
</template>的类型很简单,与接口类似:
class<template>
<input ref="el" />
</template>Animal<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>name:<template>
<input ref="el" />
</template>string
<template>
<input ref="el" />
</template>constructor(name:<template>
<input ref="el" />
</template>string)<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>this.name<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>name
<template>
<input ref="el" />
</template>}
<template>
<input ref="el" />
</template>sayHi(welcome:<template>
<input ref="el" />
</template>string):<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>`${welcome}<template>
<input ref="el" />
</template>My<template>
<input ref="el" />
</template>name<template>
<input ref="el" />
</template>is<template>
<input ref="el" />
</template>${this.name}`
<template>
<input ref="el" />
</template>}
}类的语法涉及到较多概念,请参考:

[*]https://es6.ruanyifeng.com/#docs/class
[*]https://ts.xcatliu.com/advanced/class.html
2.10<template>
<input ref="el" />
</template>泛型

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
可以简单理解为定义函数时的形参。
设想以下场景,我们有一个<template>
<input ref="el" />
</template>print<template>
<input ref="el" />
</template>函数,输入什么,原样打印,函数的入参和返回值类型是一致的。
一开始只需要打印字符串:
function<template>
<input ref="el" />
</template>print(arg:<template>
<input ref="el" />
</template>string):<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>arg
}后面需求变了,除了能打印字符串,还要能打印数字:
function<template>
<input ref="el" />
</template>print(arg:<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number):<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>arg
}假如需求又变了,要打印布尔值、对象、数组,甚至自定义的类型,怎么办,写一串联合类型?显然是不可取的,用<template>
<input ref="el" />
</template>any?那就失去了<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>类型校验能力,沦为<template>
<input ref="el" />
</template>JS。
function<template>
<input ref="el" />
</template>print(arg:<template>
<input ref="el" />
</template>any):<template>
<input ref="el" />
</template>any<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>arg
}解决这个问题的完美方法就是泛型!
print<template>
<input ref="el" />
</template>后面加上一对尖括号,里面写一个<template>
<input ref="el" />
</template>T,这个<template>
<input ref="el" />
</template>T<template>
<input ref="el" />
</template>就类似是一个类型的形参。
这个类型形参可以在函数入参里用,也可以在函数返回值使用,甚至也可以在函数体里面的变量、函数里面用。
function<template>
<input ref="el" />
</template>print<T>(arg:<template>
<input ref="el" />
</template>T):<template>
<input ref="el" />
</template>T<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>arg
}那么实参哪里来?用的时候传进来!
const<template>
<input ref="el" />
</template>res<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>print<number>(123)我们还可以使用泛型来约束后端接口参数类型。
import<template>
<input ref="el" />
</template>axios<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'axios'
interface<template>
<input ref="el" />
</template>API<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>'/book/detail':<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>id:<template>
<input ref="el" />
</template>number,
<template>
<input ref="el" />
</template>},
<template>
<input ref="el" />
</template>'/book/comment':<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>id:<template>
<input ref="el" />
</template>number
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>comment:<template>
<input ref="el" />
</template>string
<template>
<input ref="el" />
</template>}
<template>
<input ref="el" />
</template>...
}
function<template>
<input ref="el" />
</template>request<T<template>
<input ref="el" />
</template>extends<template>
<input ref="el" />
</template>keyof<template>
<input ref="el" />
</template>API>(url:<template>
<input ref="el" />
</template>T,<template>
<input ref="el" />
</template>obj:<template>
<input ref="el" />
</template>API)<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>axios.post(url,<template>
<input ref="el" />
</template>obj)
}
request('/book/comment',<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>id:<template>
<input ref="el" />
</template>1,
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>comment:<template>
<input ref="el" />
</template>'非常棒!'
})以上代码对接口进行了约束:

[*]url<template>
<input ref="el" />
</template>只能是<template>
<input ref="el" />
</template>API<template>
<input ref="el" />
</template>中定义过的,其他<template>
<input ref="el" />
</template>url<template>
<input ref="el" />
</template>都会提示错误


[*]接口参数<template>
<input ref="el" />
</template>obj<template>
<input ref="el" />
</template>必须和<template>
<input ref="el" />
</template>url<template>
<input ref="el" />
</template>能对应上,不能少属性,属性类型也不能错
而且调用<template>
<input ref="el" />
</template>request<template>
<input ref="el" />
</template>方法时,也会提示<template>
<input ref="el" />
</template>url<template>
<input ref="el" />
</template>可以选择哪些
如果后台改了接口参数名,我们一眼就看出来了,都不用去找接口文档,是不是很厉害!
泛型的例子参考了前端阿林的文章:

[*]轻松拿下<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>泛型
3<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>在<template>
<input ref="el" />
</template>Vue<template>
<input ref="el" />
</template>中的实践

3.1<template>
<input ref="el" />
</template>定义组件<template>
<input ref="el" />
</template>props<template>
<input ref="el" />
</template>的类型

不使用<template>
<input ref="el" />
</template>setup<template>
<input ref="el" />
</template>语法糖
export<template>
<input ref="el" />
</template>default<template>
<input ref="el" />
</template>defineComponent({
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>props:<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>items:<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>Object<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>PropType<IResourceItem[]>,
<template>
<input ref="el" />
</template>default()<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>[]
<template>
<input ref="el" />
</template>}
<template>
<input ref="el" />
</template>},
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>span:<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>Number,
<template>
<input ref="el" />
</template>default:<template>
<input ref="el" />
</template>4
<template>
<input ref="el" />
</template>},
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>gap:<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>[String,<template>
<input ref="el" />
</template>Number]<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>PropType<string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number>,
<template>
<input ref="el" />
</template>default:<template>
<input ref="el" />
</template>'12px'
<template>
<input ref="el" />
</template>},
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>block:<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>Object<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>PropType<Component>,
<template>
<input ref="el" />
</template>default:<template>
<input ref="el" />
</template>TvpBlock
<template>
<input ref="el" />
</template>},
<template>
<input ref="el" />
</template>beforeClose:<template>
<input ref="el" />
</template>Function<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>PropType<()<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>boolean>
<template>
<input ref="el" />
</template>}
})使用<template>
<input ref="el" />
</template>setup<template>
<input ref="el" />
</template>语法糖<template>
<input ref="el" />
</template>–<template>
<input ref="el" />
</template>runtime<template>
<input ref="el" />
</template>声明
import<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>PropType,<template>
<input ref="el" />
</template>Component<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'vue'
const<template>
<input ref="el" />
</template>props<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>defineProps({
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>items:<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>Object<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>PropType<IResourceItem[]>,
<template>
<input ref="el" />
</template>default()<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>[]
<template>
<input ref="el" />
</template>}
<template>
<input ref="el" />
</template>},
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>span:<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>Number,
<template>
<input ref="el" />
</template>default:<template>
<input ref="el" />
</template>4
<template>
<input ref="el" />
</template>},
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>gap:<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>[String,<template>
<input ref="el" />
</template>Number]<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>PropType<string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number>,
<template>
<input ref="el" />
</template>default:<template>
<input ref="el" />
</template>'12px'
<template>
<input ref="el" />
</template>},
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>block:<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>Object<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>PropType<Component>,
<template>
<input ref="el" />
</template>default:<template>
<input ref="el" />
</template>TvpBlock
<template>
<input ref="el" />
</template>},
<template>
<input ref="el" />
</template>beforeClose:<template>
<input ref="el" />
</template>Function<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>PropType<()<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>boolean>
})使用<template>
<input ref="el" />
</template>setup<template>
<input ref="el" />
</template>语法糖<template>
<input ref="el" />
</template>–<template>
<input ref="el" />
</template>type-based<template>
<input ref="el" />
</template>声明
import<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>Component,<template>
<input ref="el" />
</template>withDefaults<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'vue'
interface<template>
<input ref="el" />
</template>Props<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>items:<template>
<input ref="el" />
</template>IResourceItem[]
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>span:<template>
<input ref="el" />
</template>number
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>gap:<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>block:<template>
<input ref="el" />
</template>Component
<template>
<input ref="el" />
</template>beforeClose:<template>
<input ref="el" />
</template>()<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>void
}
const<template>
<input ref="el" />
</template>props<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>withDefaults(defineProps<Props>(),<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>items:<template>
<input ref="el" />
</template>()<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>[],
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>span:<template>
<input ref="el" />
</template>4,
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>gap:<template>
<input ref="el" />
</template>'12px',
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>block:<template>
<input ref="el" />
</template>TvpBlock
})
IResourceItem:
interface<template>
<input ref="el" />
</template>IResourceItem<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>name:<template>
<input ref="el" />
</template>string;
<template>
<input ref="el" />
</template>value?:<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number;
<template>
<input ref="el" />
</template>total?:<template>
<input ref="el" />
</template>number;
<template>
<input ref="el" />
</template>checked?:<template>
<input ref="el" />
</template>boolean;
<template>
<input ref="el" />
</template>closable?:<template>
<input ref="el" />
</template>boolean;
}3.2<template>
<input ref="el" />
</template>定义<template>
<input ref="el" />
</template>emits<template>
<input ref="el" />
</template>类型

不使用<template>
<input ref="el" />
</template>setup<template>
<input ref="el" />
</template>语法糖
export<template>
<input ref="el" />
</template>default<template>
<input ref="el" />
</template>defineComponent({
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>emits:<template>
<input ref="el" />
</template>['change',<template>
<input ref="el" />
</template>'update'],
<template>
<input ref="el" />
</template>setup(props,<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>emit<template>
<input ref="el" />
</template>})<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>emit('change')
<template>
<input ref="el" />
</template>}
})使用<template>
<input ref="el" />
</template>setup<template>
<input ref="el" />
</template>语法糖
3.3<template>
<input ref="el" />
</template>定义<template>
<input ref="el" />
</template>ref<template>
<input ref="el" />
</template>类型

默认会自动进行类型推导
import<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>ref<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'vue'
//<template>
<input ref="el" />
</template>inferred<template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>Ref<number>
const<template>
<input ref="el" />
</template>year<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>ref(2020)
//<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>Error:<template>
<input ref="el" />
</template>Type<template>
<input ref="el" />
</template>'string'<template>
<input ref="el" />
</template>is<template>
<input ref="el" />
</template>not<template>
<input ref="el" />
</template>assignable<template>
<input ref="el" />
</template>to<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>'number'.
year.value<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>'2020'两种声明<template>
<input ref="el" />
</template>ref<template>
<input ref="el" />
</template>类型的方法
import<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>ref<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'vue'
import<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>Ref<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'vue'
//<template>
<input ref="el" />
</template>方式一
const<template>
<input ref="el" />
</template>year:<template>
<input ref="el" />
</template>Ref<string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number><template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>ref('2020')
year.value<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>2020<template>
<input ref="el" />
</template>//<template>
<input ref="el" />
</template>ok!
//<template>
<input ref="el" />
</template>方式二
//<template>
<input ref="el" />
</template>resulting<template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>Ref<string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number>
const<template>
<input ref="el" />
</template>year<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>ref<string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>number>('2020')
year.value<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>2020<template>
<input ref="el" />
</template>//<template>
<input ref="el" />
</template>ok!3.4<template>
<input ref="el" />
</template>定义<template>
<input ref="el" />
</template>reactive<template>
<input ref="el" />
</template>类型

默认会自动进行类型推导
import<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>reactive<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'vue'
//<template>
<input ref="el" />
</template>inferred<template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>title:<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>}
const<template>
<input ref="el" />
</template>book<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>reactive({<template>
<input ref="el" />
</template>title:<template>
<input ref="el" />
</template>'Vue<template>
<input ref="el" />
</template>3<template>
<input ref="el" />
</template>Guide'<template>
<input ref="el" />
</template>})使用接口定义明确的类型
import<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>reactive<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'vue'
interface<template>
<input ref="el" />
</template>Book<template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>title:<template>
<input ref="el" />
</template>string
<template>
<input ref="el" />
</template>year?:<template>
<input ref="el" />
</template>number
}
const<template>
<input ref="el" />
</template>book:<template>
<input ref="el" />
</template>Book<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>reactive({<template>
<input ref="el" />
</template>title:<template>
<input ref="el" />
</template>'Vue<template>
<input ref="el" />
</template>3<template>
<input ref="el" />
</template>Guide'<template>
<input ref="el" />
</template>})3.5<template>
<input ref="el" />
</template>定义<template>
<input ref="el" />
</template>computed<template>
<input ref="el" />
</template>类型

默认会自动进行类型推导
import<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>ref,<template>
<input ref="el" />
</template>computed<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'vue'
const<template>
<input ref="el" />
</template>count<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>ref(0)
//<template>
<input ref="el" />
</template>inferred<template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>ComputedRef<number>
const<template>
<input ref="el" />
</template>double<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>computed(()<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>count.value<template>
<input ref="el" />
</template>*<template>
<input ref="el" />
</template>2)
//<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>Error:<template>
<input ref="el" />
</template>Property<template>
<input ref="el" />
</template>'split'<template>
<input ref="el" />
</template>does<template>
<input ref="el" />
</template>not<template>
<input ref="el" />
</template>exist<template>
<input ref="el" />
</template>on<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>'number'
const<template>
<input ref="el" />
</template>result<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>double.value.split('')两种声明<template>
<input ref="el" />
</template>computed<template>
<input ref="el" />
</template>类型的方法
import<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>ComputedRef,<template>
<input ref="el" />
</template>computed<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'vue'
const<template>
<input ref="el" />
</template>double:<template>
<input ref="el" />
</template>ComputedRef<number><template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>computed(()<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>//<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>error<template>
<input ref="el" />
</template>if<template>
<input ref="el" />
</template>this<template>
<input ref="el" />
</template>doesn't<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>a<template>
<input ref="el" />
</template>number
})
const<template>
<input ref="el" />
</template>double<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>computed<number>(()<template>
<input ref="el" />
</template>=><template>
<input ref="el" />
</template>{
<template>
<input ref="el" />
</template>//<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>error<template>
<input ref="el" />
</template>if<template>
<input ref="el" />
</template>this<template>
<input ref="el" />
</template>doesn't<template>
<input ref="el" />
</template>return<template>
<input ref="el" />
</template>a<template>
<input ref="el" />
</template>number
})3.6<template>
<input ref="el" />
</template>定义<template>
<input ref="el" />
</template>provide/inject<template>
<input ref="el" />
</template>类型

provide
import<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>provide,<template>
<input ref="el" />
</template>inject<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'vue'
import<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>InjectionKey<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>from<template>
<input ref="el" />
</template>'vue'
//<template>
<input ref="el" />
</template>声明<template>
<input ref="el" />
</template>provide<template>
<input ref="el" />
</template>的值为<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>类型
const<template>
<input ref="el" />
</template>key<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>Symbol()<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>InjectionKey<string>
provide(key,<template>
<input ref="el" />
</template>'foo')<template>
<input ref="el" />
</template>//<template>
<input ref="el" />
</template>providing<template>
<input ref="el" />
</template>non-string<template>
<input ref="el" />
</template>value<template>
<input ref="el" />
</template>will<template>
<input ref="el" />
</template>result<template>
<input ref="el" />
</template>in<template>
<input ref="el" />
</template>errorinject
//<template>
<input ref="el" />
</template>自动推导为<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>类型
const<template>
<input ref="el" />
</template>foo<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>inject(key)<template>
<input ref="el" />
</template>//<template>
<input ref="el" />
</template>type<template>
<input ref="el" />
</template>of<template>
<input ref="el" />
</template>foo:<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>undefined
//<template>
<input ref="el" />
</template>明确指定为<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>类型
const<template>
<input ref="el" />
</template>foo<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>inject<string>('foo')<template>
<input ref="el" />
</template>//<template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>string<template>
<input ref="el" />
</template>|<template>
<input ref="el" />
</template>undefined
//<template>
<input ref="el" />
</template>增加默认值
const<template>
<input ref="el" />
</template>foo<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>inject<string>('foo',<template>
<input ref="el" />
</template>'bar')<template>
<input ref="el" />
</template>//<template>
<input ref="el" />
</template>type:<template>
<input ref="el" />
</template>string
//<template>
<input ref="el" />
</template>类型断言为<template>
<input ref="el" />
</template>string
const<template>
<input ref="el" />
</template>foo<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>inject('foo')<template>
<input ref="el" />
</template>as<template>
<input ref="el" />
</template>string3.7<template>
<input ref="el" />
</template>定义模板引用的类型

<template>
<input ref="el" />
</template>3.8<template>
<input ref="el" />
</template>定义组件模板引用的类型

定义一个<template>
<input ref="el" />
</template>MyModal<template>
<input ref="el" />
</template>组件
在<template>
<input ref="el" />
</template>App.vue<template>
<input ref="el" />
</template>中引用<template>
<input ref="el" />
</template>MyModal<template>
<input ref="el" />
</template>组件
参考<template>
<input ref="el" />
</template>Vue<template>
<input ref="el" />
</template>官网文档:

[*]TypeScript<template>
<input ref="el" />
</template>with<template>
<input ref="el" />
</template>Composition<template>
<input ref="el" />
</template>API
4<template>
<input ref="el" />
</template>JS<template>
<input ref="el" />
</template>项目转<template>
<input ref="el" />
</template>TS

还是使用<template>
<input ref="el" />
</template>JS<template>
<input ref="el" />
</template>的同学有福啦!为了让大家快速用上<template>
<input ref="el" />
</template>TS,享受<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>的丝滑体验,我整理了一份《JS<template>
<input ref="el" />
</template>项目改造成<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>项目指南》。有了这份步骤指南,JS<template>
<input ref="el" />
</template>项目转<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>不再是难事!
我们新开源的<template>
<input ref="el" />
</template>TinyVue<template>
<input ref="el" />
</template>组件库,就使用这份《JS<template>
<input ref="el" />
</template>项目改造成<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>项目指南》,成功地由<template>
<input ref="el" />
</template>JS<template>
<input ref="el" />
</template>项目改造成了<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>项目,悄悄地告诉大家:

[*]TinyVue 是一套跨端、跨框架的企业级<template>
<input ref="el" />
</template>UI<template>
<input ref="el" />
</template>组件库,支持<template>
<input ref="el" />
</template>Vue<template>
<input ref="el" />
</template>2<template>
<input ref="el" />
</template>和<template>
<input ref="el" />
</template>Vue<template>
<input ref="el" />
</template>3,支持<template>
<input ref="el" />
</template>PC<template>
<input ref="el" />
</template>端和移动端。
[*]在内部经过9年持续打磨,服务于华为内外部上千个项目。
[*]目前代码量超过10万行。
这么庞大的代码量都能从<template>
<input ref="el" />
</template>JS<template>
<input ref="el" />
</template>转<template>
<input ref="el" />
</template>TS,其他小规模的项目更是不在话下。
为了验证自己的猜想,我又在<template>
<input ref="el" />
</template>GitHub<template>
<input ref="el" />
</template>找到了一个6年前的<template>
<input ref="el" />
</template>Vue2<template>
<input ref="el" />
</template>+<template>
<input ref="el" />
</template>JS<template>
<input ref="el" />
</template>项目,目前早已不再维护,打算尝试将其改造成<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>项目,结果按照这份指南,1个小时不用就搞定啦啦
https://github.com/liangxiaojuan/vue-todos
这个项目的效果图长这样:
我已经提了<template>
<input ref="el" />
</template>issue,看下作者是否同意改造成<template>
<input ref="el" />
</template>TS,同意的话,我立马就是一个<template>
<input ref="el" />
</template>PR<template>
<input ref="el" />
</template>过去!
话不多说,大家有需要的,可直接拿走!
《JS<template>
<input ref="el" />
</template>项目改造成<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>项目指南》

JS<template>
<input ref="el" />
</template>项目改造成<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>步骤:

[*]安装<template>
<input ref="el" />
</template>TS:npm<template>
<input ref="el" />
</template>i<template>
<input ref="el" />
</template>typescript<template>
<input ref="el" />
</template>ts-loader<template>
<input ref="el" />
</template>-D
[*]增加<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>配置文件:tsconfig.json
[*]修改文件后缀名:x.js<template>
<input ref="el" />
</template>-><template>
<input ref="el" />
</template>x.ts
[*]x.vue<template>
<input ref="el" />
</template>文件增加<template>
<input ref="el" />
</template>lang:<script<template>
<input ref="el" />
</template>lang="ts">
[*]vite.config.js<template>
<input ref="el" />
</template>配置后缀名
[*]升级依赖,修改本地启动和构建脚本
[*]添加<template>
<input ref="el" />
</template>loader<template>
<input ref="el" />
</template>/<template>
<input ref="el" />
</template>plugin<template>
<input ref="el" />
</template>等
[*]逐步补充类型声明
tsconfig.ts
{<template>
<input ref="el" />
</template>"compilerOptions":<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>"target":<template>
<input ref="el" />
</template>"ESNext",<template>
<input ref="el" />
</template>"useDefineForClassFields":<template>
<input ref="el" />
</template>true,<template>
<input ref="el" />
</template>"module":<template>
<input ref="el" />
</template>"ESNext",<template>
<input ref="el" />
</template>"moduleResolution":<template>
<input ref="el" />
</template>"Node",<template>
<input ref="el" />
</template>"strict":<template>
<input ref="el" />
</template>true,<template>
<input ref="el" />
</template>"jsx":<template>
<input ref="el" />
</template>"preserve",<template>
<input ref="el" />
</template>"sourceMap":<template>
<input ref="el" />
</template>true,<template>
<input ref="el" />
</template>"resolveJsonModule":<template>
<input ref="el" />
</template>true,<template>
<input ref="el" />
</template>"isolatedModules":<template>
<input ref="el" />
</template>true,<template>
<input ref="el" />
</template>"esModuleInterop":<template>
<input ref="el" />
</template>true,<template>
<input ref="el" />
</template>"lib":<template>
<input ref="el" />
</template>["ESNext",<template>
<input ref="el" />
</template>"DOM"],<template>
<input ref="el" />
</template>"skipLibCheck":<template>
<input ref="el" />
</template>true<template>
<input ref="el" />
</template>},<template>
<input ref="el" />
</template>"include":<template>
<input ref="el" />
</template>[<template>
<input ref="el" />
</template>"src/**/*.ts",<template>
<input ref="el" />
</template>"src/**/*.d.ts",<template>
<input ref="el" />
</template>"src/**/*.tsx",<template>
<input ref="el" />
</template>"src/**/*.vue"<template>
<input ref="el" />
</template>]}配置文件后缀名,增加<template>
<input ref="el" />
</template>.ts<template>
<input ref="el" />
</template>和<template>
<input ref="el" />
</template>.tsx
extensions:<template>
<input ref="el" />
</template>['.js',<template>
<input ref="el" />
</template>'.vue',<template>
<input ref="el" />
</template>'.json',<template>
<input ref="el" />
</template>'.ts',<template>
<input ref="el" />
</template>'tsx'],入口文件要由<template>
<input ref="el" />
</template>main.js<template>
<input ref="el" />
</template>改成<template>
<input ref="el" />
</template>main.tsentry:<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>app:<template>
<input ref="el" />
</template>'./src/main.ts'},需要配置下<template>
<input ref="el" />
</template>loader
{<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>test:<template>
<input ref="el" />
</template>/\.tsx?$/,<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>loader:<template>
<input ref="el" />
</template>'ts-loader',<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>exclude:<template>
<input ref="el" />
</template>/node_modules/,<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>options:<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>appendTsSuffixTo:<template>
<input ref="el" />
</template>[/\.vue$/]<template>
<input ref="el" />
</template>},<template>
<input ref="el" />
</template><template>
<input ref="el" />
</template>include:<template>
<input ref="el" />
</template>}以及<template>
<input ref="el" />
</template>plugin
const<template>
<input ref="el" />
</template>{<template>
<input ref="el" />
</template>VueLoaderPlugin<template>
<input ref="el" />
</template>}<template>
<input ref="el" />
</template>=<template>
<input ref="el" />
</template>require('vue-loader')plugins:<template>
<input ref="el" />
</template>[<template>
<input ref="el" />
</template>new<template>
<input ref="el" />
</template>VueLoaderPlugin()],完成之后,先测试下项目是否能正常启动和构建:npm<template>
<input ref="el" />
</template>run<template>
<input ref="el" />
</template>dev<template>
<input ref="el" />
</template>/<template>
<input ref="el" />
</template>npm<template>
<input ref="el" />
</template>run<template>
<input ref="el" />
</template>build
都没问题之后,本次<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>项目改造就完成大部分啦啦!
后续就是逐步补充代码涉及到的变量和函数的类型声明即可。
改造过程中遇到问题欢迎留言讨论,希望你也能尽快享受<template>
<input ref="el" />
</template>TS<template>
<input ref="el" />
</template>的丝滑开发者体验!
TinyVue<template>
<input ref="el" />
</template>招募贡献者啦

如果你对我们的跨端跨框架组件库 TinyVue 感兴趣,欢迎参与到我们的开源社区中来,一起将它建设得更好!
参与<template>
<input ref="el" />
</template>TinyVue<template>
<input ref="el" />
</template>组件库建设,你将收获:
直接的价值:

[*]通过打造一个跨端、跨框架的组件库项目,学习最新的<template>
<input ref="el" />
</template>Monorepo<template>
<input ref="el" />
</template>+<template>
<input ref="el" />
</template>Vite<template>
<input ref="el" />
</template>+<template>
<input ref="el" />
</template>Vue3<template>
<input ref="el" />
</template>+<template>
<input ref="el" />
</template>TypeScript<template>
<input ref="el" />
</template>技术
[*]学习从<template>
<input ref="el" />
</template>0<template>
<input ref="el" />
</template>到<template>
<input ref="el" />
</template>1<template>
<input ref="el" />
</template>搭建一个自己的组件库的整套流程和方法论,包括组件库工程化、组件的设计和开发等
[*]为自己的简历和职业生涯添彩,参与过优秀的开源项目,这本身就是受面试官青睐的亮点
[*]结识一群优秀的、热爱学习、热爱开源的小伙伴,大家一起打造一个伟大的产品
长远的价值:

[*]打造个人品牌,提升个人影响力
[*]培养良好的编码习惯
[*]获得华为云<template>
<input ref="el" />
</template>OpenTiny<template>
<input ref="el" />
</template>开源社区的荣誉&认可和定制小礼物
[*]成为<template>
<input ref="el" />
</template>PMC<template>
<input ref="el" />
</template>&<template>
<input ref="el" />
</template>Committer<template>
<input ref="el" />
</template>之后还能参与<template>
<input ref="el" />
</template>OpenTiny<template>
<input ref="el" />
</template>整个开源生态的决策和长远规划,培养自己的管理和规划能力。
[*]未来有更多机会和可能
往期活动礼品及贡献者的反馈:
联系我们

如果你对我们<template>
<input ref="el" />
</template>OpenTiny<template>
<input ref="el" />
</template>的开源项目感兴趣,欢迎添加小助手微信:opentiny-official,拉你进群,一起交流前端技术,一起玩开源。
OpenTiny<template>
<input ref="el" />
</template>官网:https://opentiny.design/
OpenTiny<template>
<input ref="el" />
</template>仓库:https://github.com/opentiny/

Vue<template>
<input ref="el" />
</template>组件库:https://github.com/opentiny/tiny-vue(欢迎<template>
<input ref="el" />
</template>Star<template>
<input ref="el" />
</template>
来源:https://www.cnblogs.com/huaweiyun/p/17302482.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】<template>
<input ref="el" />
</template>我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: OpenTiny 跨端、跨框架组件库升级TypeScript,10万行代码重获新生