重新认识Typescript|Vue3源码系列

初次见面

官方对其只用了一句话来描述

创新互联主营阿尔山网站建设的网络公司,主营网站建设方案,APP应用开发,阿尔山h5成都小程序开发搭建,阿尔山网站营销推广欢迎阿尔山等地区企业咨询

TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open source.

大致意思为,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 的基本使用。

变量申明

基本类型

 
 
 
  1. let isDone: boolean = false
  2. let num: number = 1
  3. let str: string = 'vue3js.cn'
  4. let arr: number[] = [1, 2, 3] 
  5. let arr2: Array = [1, 2, 3] // 泛型数组
  6. let obj: Object = {}
  7. let u: undefined = undefined;
  8. let n: null = null;

类型补充

  • 枚举 Enum

使用枚举类型可以为一组数值赋予友好的名字

 
 
 
  1. enum LogLevel {
  2.   info = 'info',
  3.   warn = 'warn',
  4.   error = 'error',
  5. }
  • 元组 Tuple

允许数组各元素的类型不必相同。比如,你可以定义一对值分别为 string和number类型的元组

 
 
 
  1. // Declare a tuple type
  2. let x: [string, number];
  3. // Initialize it
  4. x = ['hello', 10]; // OK
  5. // Initialize it incorrectly
  6. x = [10, 'hello']; // Error
  • 任意值 Any

表示任意类型,通常用于不确定内容的类型,比如来自用户输入或第三方代码库

 
 
 
  1. let notSure: any = 4;
  2. notSure = "maybe a string instead";
  3. notSure = false; // okay, definitely a boolean
  • 空值 Void

与 any 相反,通常用于函数,表示没有返回值

 
 
 
  1. function warnUser(): void {
  2.     console.log("This is my warning message");
  3. }
  • 接口 interface

类型契约,跟我们平常调服务端接口要先定义字段一个理

如下例子 point 跟 Point 类型必须一致,多一个少一个也是不被允许的

 
 
 
  1. interface Point {
  2.     x: number
  3.     y: number
  4.     z?: number
  5.     readonly l: number
  6. }
  7. const point: Point = { x: 10, y: 20, z: 30, l: 40 }
  8. const point2: Point = { x: '10', y: 20, z: 30, l: 40 } // Error 
  9. const point3: Point = { x: 10, y: 20, z: 30 } // Error 
  10. const point4: Point = { x: 10, y: 20, z: 30, l: 40, m: 50 } // Error 

可选与只读 ? 表示可选参, readonly 表示只读

 
 
 
  1. const point5: Point = { x: 10, y: 20, l: 40 } // 正常
  2. point5.l = 50 // error

函数参数类型与返回值类型

 
 
 
  1. function sum(a: number, b: number): number {
  2.     return a + b
  3. }

配合 interface 使用

 
 
 
  1. interface Point {
  2.     x: number
  3.     y: number
  4. }
  5. function sum({ x,  y}: Point): number {
  6.     return x + y
  7. }
  8. sum({x:1, y:2}) // 3

泛型

泛型的意义在于函数的重用性,设计原则希望组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型

  • 比如

根据业务最初的设计函数 identity 入参为String

 
 
 
  1. function identity(arg: String){
  2.  return arg
  3. }
  4. console.log(identity('100'))

业务迭代过程参数需要支持 Number

 
 
 
  1. function identity(arg: String){
  2.  return arg
  3. }
  4. console.log(identity(100)) // Argument of type '100' is not assignable to parameter of type 'String'.

为什么不用any呢?

使用 any 会丢失掉一些信息,我们无法确定返回值是什么类型

泛型可以保证入参跟返回值是相同类型的,它是一种特殊的变量,只用于表示类型而不是值

语法 (arg:T):T 其中T为自定义变量

 
 
 
  1. const hello : string = "Hello vue!"
  2. function say(arg: T): T {
  3.     return arg;
  4. }
  5. console.log(say(hello)) // Hello vue! 

泛型约束

我们使用同样的例子,加了一个console,但是很不幸运,报错了,因为泛型无法保证每种类型都有.length 属性

 
 
 
  1. const hello : string = "Hello vue!"
  2. function say(arg: T): T {
  3.  console.log(arg.length) // Property 'length' does not exist on type 'T'.
  4.     return arg;
  5. }
  6. console.log(say(hello)) // Hello vue! 

从这里我们也又看出来一个跟any不同的地方,如果我们想要在约束层面上就结束战斗,我们需要定义一个接口来描述约束条件

 
 
 
  1. interface Lengthwise {
  2.     length: number;
  3. }
  4. function say(arg: T): T {
  5.  console.log(arg.length)
  6.     return arg;
  7. }
  8. console.log(say(1))  // Argument of type '1' is not assignable to parameter of type 'Lengthwise'.
  9. console.log(say({value: 'hello vue!', length: 10})) // { value: 'hello vue!', length: 10 } 

交叉类型

交叉类型(Intersection Types),将多个类型合并为一个类型

 
 
 
  1. interface foo {
  2.     x: number
  3. }
  4. interface bar {
  5.     b: number
  6. }
  7. type intersection = foo & bar
  8. const result: intersection = {
  9.     x: 10,
  10.     b: 20
  11. }
  12. const result1: intersection = {
  13.     x: 10
  14. }  // error

联合类型

交叉类型(Union Types),表示一个值可以是几种类型之一。我们用竖线 | 分隔每个类型,所以 number | string | boolean表示一个值可以是 number, string,或 boolean

 
 
 
  1. type arg = string | number | boolean
  2. const foo = (arg: arg):any =>{ 
  3.     console.log(arg)
  4. }
  5. foo(1)
  6. foo('2')
  7. foo(true)

函数重载

函数重载(Function Overloading), 允许创建数项名称相同但输入输出类型或个数不同的子程序,可以简单理解为一个函数可以执行多项任务的能力

例我们有一个add函数,它可以接收string类型的参数进行拼接,也可以接收number类型的参数进行相加

 
 
 
  1. function add (arg1: string, arg2: string): string
  2. function add (arg1: number, arg2: number): number
  3. // 实现
  4. function add (arg1: T, arg2: U) {
  5.   // 在实现上我们要注意严格判断两个参数的类型是否相等,而不能简单的写一个 arg1 + arg2
  6.   if (typeof arg1 === 'string' && typeof arg2 === 'string') {
  7.     return arg1 + arg2
  8.   } else if (typeof arg1 === 'number' && typeof arg2 === 'number') {
  9.     return arg1 + arg2
  10.   }
  11. }
  12. add(1, 2) // 3
  13. add('1','2') //'12'

总结

通过本篇文章,相信大家对Typescript不会再感到陌生了

下面我们来看看在Vue源码Typescript是如何书写的,这里我们以defineComponent函数为例,大家可以通过这个实例,再结合文章的内容,去理解,加深Typescript的认识

 
 
 
  1. // overload 1: direct setup function
  2. export function defineComponent(
  3.   setup: (
  4.     props: Readonly,
  5.     ctx: SetupContext
  6.   ) => RawBindings | RenderFunction
  7. ): {
  8.   new (): ComponentPublicInstance<
  9.     Props,
  10.     RawBindings,
  11.     {},
  12.     {},
  13.     {},
  14.     // public props
  15.     VNodeProps & Props
  16.   >
  17. } & FunctionalComponent
  18. // defineComponent一共有四个重载,这里省略三个
  19. // implementation, close to no-op
  20. export function defineComponent(options: unknown) {
  21.   return isFunction(options) ? { setup: options } : options
  22. }

当前文章:重新认识Typescript|Vue3源码系列
URL链接:http://www.shufengxianlan.com/qtweb/news39/120739.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联