Typescript | Vue3源码系列
TypeScript 是开源的,TypeScript 是 JavaScript 的类型的超集,它可以编译成纯 JavaScript。编译出来的 JavaScript 可以运行在任何浏览器上。TypeScript 编译工具可以运行在任何服务器和任何系统上
- 问题: 什么是超集
超集是集合论的术语
说到超集,不得不说另一个,子集,怎么理解这两个概念呢,举个例子
如果一个集合A里面的的所有元素集合B里面都存在,那么我们可以理解集合A是集合B的子集,反之集合B为集合A的超集
现在我们就能理解为 Typescript 里包含了 Javascript 的所有特性,这也意味着我们可以将.js后缀直接命名为.ts文件跑到TypeScript的编绎系统中
Typescript 解决了什么问题
一个事物的诞生一定会有其存在的价值
那么 Typescript 的价值是什么呢?
回答这个问题之前,我们有必要先来了解一下 Typescript 的工作理念
本质上是在 JavaScript 上增加一套静态类型系统(编译时进行类型分析),强调静态类型系统是为了和运行时的类型检查机制做区分,TypeScript 的代码最终会被编译为 JavaScript
我们再回到问题本身,缩小一下范围,Typescript 创造的价值大部分是在开发时体现的(编译时),而非运行时,如
- 强大的编辑器智能提示 (研发效率,开发体验)
- 代码可读性增强 (团队协作,开发体验)
- 编译时类型检查 (业务稳健,前端项目中Top10 的错误类型低级的类型错误占比达到70%)
正文
本篇文章作为
Vue3源码系列前置篇章之一,Typescript的科普文,主要目的为了大家在面对Vue3源码时不会显得那么不知所措,下来将介绍一些Typescript的基本使用变量申明
基本类型
let isDone: boolean = false
let num: number = 1
let str: string = 'vue3js.cn'
let arr: number[] = [1, 2, 3]
let arr2: Array<number> = [1, 2, 3] // 泛型数组
let obj: Object = {}
let u: undefined = undefined;
let n: null = null;类型补充
- 枚举
Enum
使用枚举类型可以为一组数值赋予友好的名字
enum LogLevel {
info = 'info',
warn = 'warn',
error = 'error',
}- 元组
Tuple
允许数组各元素的类型不必相同。比如,你可以定义一对值分别为 string和number类型的元组
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error- 任意值
Any
表示任意类型,通常用于不确定内容的类型,比如来自用户输入或第三方代码库
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean- 空值
Void
与 any 相反,通常用于函数,表示没有返回值
function warnUser(): void {
console.log("This is my warning message");
}- 接口
interface
类型契约,跟我们平常调服务端接口要先定义字段一个理
如下例子 point 跟 Point 类型必须一致,多一个少一个也是不被允许的
interface Point {
x: number
y: number
z?: number
readonly l: number
}
const point: Point = { x: 10, y: 20, z: 30, l: 40 }
const point2: Point = { x: '10', y: 20, z: 30, l: 40 } // Error
const point3: Point = { x: 10, y: 20, z: 30 } // Error
const point4: Point = { x: 10, y: 20, z: 30, l: 40, m: 50 } // Error
可选与只读 ? 表示可选参, readonly 表示只读
const point5: Point = { x: 10, y: 20, l: 40 } // 正常
point5.l = 50 // error函数参数类型与返回值类型
function sum(a: number, b: number): number {
return a + b
}配合
interface使用interface Point {
x: number
y: number
} function sum({ x, y}: Point): number {
return x + y
} sum({x:1, y:2}) // 3泛型
泛型的意义在于函数的重用性,设计原则希望组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型
- 比如
根据业务最初的设计函数
identity入参为Stringfunction identity(arg: String){
return arg
}
console.log(identity('100'))业务迭代过程参数需要支持
Numberfunction identity(arg: String){
return arg
}
console.log(identity(100)) // Argument of type '100' is not assignable to parameter of type 'String'.为什么不用
any呢?使用
any会丢失掉一些信息,我们无法确定返回值是什么类型
泛型可以保证入参跟返回值是相同类型的,它是一种特殊的变量,只用于表示类型而不是值语法
<T>(arg:T):T其中T为自定义变量const hello : string = "Hello vue!"
function say<T>(arg: T): T {
return arg;
}
console.log(say(hello)) // Hello vue!泛型约束
我们使用同样的例子,加了一个
console,但是很不幸运,报错了,因为泛型无法保证每种类型都有.length属性const hello : string = "Hello vue!"
function say<T>(arg: T): T {
console.log(arg.length) // Property 'length' does not exist on type 'T'.
return arg;
}
console.log(say(hello)) // Hello vue!从这里我们也又看出来一个跟
any不同的地方,如果我们想要在约束层面上就结束战斗,我们需要定义一个接口来描述约束条件interface Lengthwise {
length: number;
} function say<T extends Lengthwise>(arg: T): T {
console.log(arg.length)
return arg;
}
console.log(say(1)) // Argument of type '1' is not assignable to parameter of type 'Lengthwise'.
console.log(say({value: 'hello vue!', length: 10})) // { value: 'hello vue!', length: 10 }交叉类型
交叉类型(Intersection Types),将多个类型合并为一个类型
interface foo {
x: number
}
interface bar {
b: number
}
type intersection = foo & bar
const result: intersection = {
x: 10,
b: 20
}
const result1: intersection = {
x: 10
} // error联合类型
交叉类型(Union Types),表示一个值可以是几种类型之一。我们用竖线 | 分隔每个类型,所以 number | string | boolean表示一个值可以是 number, string,或 boolean
type arg = string | number | boolean
const foo = (arg: arg):any =>{
console.log(arg)
}
foo(1)
foo('2')
foo(true)函数重载
函数重载(Function Overloading), 允许创建数项名称相同但输入输出类型或个数不同的子程序,可以简单理解为一个函数可以执行多项任务的能力
例我们有一个
add函数,它可以接收string类型的参数进行拼接,也可以接收number类型的参数进行相加function add (arg1: string, arg2: string): string
function add (arg1: number, arg2: number): number // 实现
function add <T,U>(arg1: T, arg2: U) {
// 在实现上我们要注意严格判断两个参数的类型是否相等,而不能简单的写一个 arg1 + arg2
if (typeof arg1 === 'string' && typeof arg2 === 'string') {
return arg1 + arg2
} else if (typeof arg1 === 'number' && typeof arg2 === 'number') {
return arg1 + arg2
}
} add(1, 2) // 3
add('1','2') //'12'总结
通过本篇文章,相信大家对
Typescript不会再感到陌生了下面我们来看看在
Vue源码Typescript是如何书写的,这里我们以defineComponent函数为例,大家可以通过这个实例,再结合文章的内容,去理解,加深Typescript的认识// overload 1: direct setup function
export function defineComponent<Props, RawBindings = object>(
setup: (
props: Readonly<Props>,
ctx: SetupContext
) => RawBindings | RenderFunction
): {
new (): ComponentPublicInstance<
Props,
RawBindings,
{},
{},
{},
// public props
VNodeProps & Props
>
} & FunctionalComponent<Props> // defineComponent一共有四个重载,这里省略三个 // implementation, close to no-op
export function defineComponent(options: unknown) {
return isFunction(options) ? { setup: options } : options
} - 枚举
Typescript | Vue3源码系列的更多相关文章
- 手牵手,从零学习Vue源码 系列一(前言-目录篇)
系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 手牵手,从零学习Vue源码 系列三(虚拟DOM篇) 陆续更新中... 预计八月中旬更新 ...
- vue3源码难学,先从petite-vue开始吧
如今这个世道,作为一个有几年工作经验的前端,不学点框架源码都感觉要被抛弃了,react或vue要能吹吹牛吧,最好能造个轮子,听说vue3源码好学点,那么学学vue3,但是学起来还是那么费劲,感觉快放弃 ...
- 事件机制-Spring 源码系列(4)
事件机制-Spring 源码系列(4) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProcess ...
- Ioc容器依赖注入-Spring 源码系列(2)
Ioc容器依赖注入-Spring 源码系列(2) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostPr ...
- Ioc容器BeanPostProcessor-Spring 源码系列(3)
Ioc容器BeanPostProcessor-Spring 源码系列(3) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Io ...
- AOP执行增强-Spring 源码系列(5)
AOP增强实现-Spring 源码系列(5) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProc ...
- 大白话Vue源码系列(02):编译器初探
阅读目录 编译器代码藏在哪 Vue.prototype.$mount 构建 AST 的一般过程 Vue 构建的 AST 题接上文,上回书说到,Vue 的编译器模块相对独立且简单,那咱们就从这块入手,先 ...
- 大白话Vue源码系列(03):生成AST
阅读目录 AST 节点定义 标签的正则匹配 解析用到的工具方法 解析开始标签 解析结束标签 解析文本 解析整块 HTML 模板 未提及的细节 本篇探讨 Vue 根据 html 模板片段构建出 AST ...
- 大白话Vue源码系列(03):生成render函数
阅读目录 优化 AST 生成 render 函数 小结 本来以为 Vue 的编译器模块比较好欺负,结果发现并没有那么简单.每一种语法指令都要考虑到,处理起来相当复杂.上篇已经生成了 AST,本篇依然对 ...
随机推荐
- 实战:docker搭建FastDFS文件系统并集成SpringBoot
实战:docker搭建FastDFS文件系统并集成SpringBoot 前言 15年的时候,那时候云存储还远远没有现在使用的这么广泛,归根结底就是成本和安全问题,记得那时候我待的公司是做建站开发的,前 ...
- scala下划线的用法
1.作为“通配符”,类似Java中的*.如import scala.math._2.:_*作为一个整体,告诉编译器你希望将某个参数当作参数序列处理!例如val s = sum(1 to 5:_*)就是 ...
- markdown利器-小书匠
markdown利器-小书匠 为什么要用markdown语法编写文档? 编写文档的好处这里就不多说了.相信很多人都会在一些博客网站上发布自己的博客,那么怎么能使得自己的博客内容更加具有通用性呢?正如j ...
- Taurus.MVC 2.3.4 :WebAPI 文档集成测试功能升级:WebAPI批量自动化测试功能。
前言: 最近升级了一下Taurus.MVC,现在最新版本是:Taurus.MVC 2.3.4,源码版本和nuget同步. 下面分三个步骤介绍下新版本的WebAPI批量自动化测试功能. 1.启用WebA ...
- [问题记录] webpack devServer HtmlWebpackPlugin 没有加载 js、css
webpack devServer 没有加载 js.css HtmlWebpackPlugin runtimeChunks 注入问题. 描述 写了一个极其简单的多页面 demo 启动开发服务器,发现样 ...
- (数据科学学习手札92)利用query()与eval()优化pandas代码
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 利用pandas进行数据分析的过程,不仅仅是计算 ...
- MySQL回表查询
一.MySQL索引类型 1.普通索引:最基本的索引,没有任何限制 2.唯一索引(unique index):索引列的值必须唯一,但是允许为空 3.主键索引:特殊的唯一索引,但是不允许为空,一般在建表的 ...
- XCTF-WEB-高手进阶区-Web_python_template_injection-笔记
Web_python_template_injection o(╥﹏╥)o从这里开始题目就变得有点诡谲了 网上搜索相关教程的确是一知半解,大概参考了如下和最后的WP: http://shaobaoba ...
- Java中的注解及自定义注解你用的怎么样,能不能像我这样应用自如?
Java注解提供了关于代码的一些信息,但并不直接作用于它所注解的代码内容.在这个教程当中,我们将学习Java的注解,如何定制注解,注解的使用以及如何通过反射解析注解. Java1.5引入了注解,当前许 ...
- 36 个JS 面试题
1.JS中let和const有什么用? 在现代js中,let&const是创建变量的不同方式. 在早期的js中,咱们使用var关键字来创建变量. let&const关键字是在ES6版本 ...