类型基础

在强类型语言中,当一个对象从调用函数传递到被调用函数时,其类型必须与被调用函数中声明的类型兼容
强类型语言不允许改变变量的数据类型,除非进行强制类型转换
弱类型语言中,变量可以被赋予不同的数据类型

静态类型语言:在编译阶段确定所有变量的类型(如c++)
1. 对类型要求极其严格
2. 立即发现错误
3. 运行时性能较好
4. 自文档化
动态类型语言:在执行阶段确定所有变量的类型(如js)
1. 对类型非常宽松
2. Bug可能隐藏很久
3. 运行性能较差
4. 可读性差

注意:有人提出强类型语言在程序发生错误后不允许继续执行,但是c++并没有对数组越界进行处理,所以认为它是弱类型语言。(归属特殊定义).

语言象限图

                    强类型
^
|
Python————————|——————— Java C#
动态类型———————————————|————————C——C++————>静态类型
JavaScript |
PHP |
弱类型

注意:如果把ts当做一门语言看待,那么它是强类型还是弱类型,是静态类型还是动态类型

我认为是静态+强类型语言

ts基础

webpack 配置

webpack的配置写在build文件夹里,对应的去安装npm包,项目想要使用的包写在package.json文件中。

生产和开发环境对应的其实是webpack的不同配置文件。

打包对应的也是一个webpack的文件

  1. 项目启动不起来,报如下错误
errno: 'ENOTFOUND',
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'localhost'

刚开始怎么改配置文件都不对,后来仔细看了看提示,再网上搜了一下,发现是host绑定的不对,然后去看了下自己的host文件,果然,localhost绑定的并不是本地的。修改host即可正常启动。

  1. 安装包的时候如果没有指定版本安装就会报找不到包的错误

会报E404的问题,Not Found - GET http://r.cnpmjs.org/typecript - [not_found] document not found,这个问题我还没有找到为什么,现在是通过安装指定版本的包来解决的。

有可能:

  1. 基于-D依赖安装,npm自动安装的版本没有对应的依赖,所以安装错误

基本类型

类型系统

类型系统

类型注解

作用:相当于强类型语言中的类型声明

语法:(变量/函数):type

  1. 变量的基本类型定义之后就不可改变

联合类型

表示数组的类型既可以是number也可以是string类型。

let arr2: Array<number | string> = [1, 2, 3, '4']

元组

可以通过push方法为元组新增元素,但无法对越界元素进行访问。开发过程中不建议这样使用。

undefined && null

在ts文档中,undefined和null是任何类型的子类型可以被赋值给任意类型。可以通过设置tsconfig.json中的”strictNullChecks”: false来避免报错

void

void类型标识没有任何返回值的函数或方法

any类型

不标识类型,非特殊情况,不建议使用any类型。通过any类型实现对js的兼容

never

表示永远不会有返回值的类型,比如一个函数抛出了一个异常,还有死循环函数

枚举类型

一组有名字的常量集合,enum关键字。

数字枚举 && 字符串枚举

数字枚举的实现原理为反向映射。

但字符串枚举不是反向映射

异构枚举

当数字枚举和字符串枚举混合使用就形成了异构枚举,但是不建议这样做

枚举成员

枚举成员的值在定义后变为只读类型,在定义之后是不能修改的

const member

  1. 无初始值
  2. 对已有枚举成员的引用
  3. 常量表达式
// const member
a,
b = Char.a,
c = 1 + 3,

computed member

  1. 这些值会在程序执行的时候被赋值,而不是在编译阶段
d = Math.random(),
e = '123'.length,
f = 4

在此状态下的,枚举成员必须需要初始值。

常量枚举

const enum Month {
Jan,
Feb,
Mar,
Apr = Month.Mar + 1,
// May = () => 5
}

常量枚举会在编译阶段被移除。当我们不需要一个对象,但需要对象的值得时候可以使用常量枚举

接口

  1. 接口约束对象 函数 类的结构
  2. 对象的接口如何定义
  3. 关键字 interface
  4. 作用 :规范对象的属性 属性的类型 属性值的类型
  5. 类型断言 用as 或者<>的形式 ,后者在react中使用会出问题
  6. 可选属性 通过?来设置
  7. 只读属性 通过readonly 来设置
  8. 当不确定接口中属性个数时需要使用 索引签名
  9. 索引签名包括字符串索引签名和数字索引签名
  10. 当接口中定义了一个索引后,例如设置了 【x:string】= string,就不能设置y:number了。
    因为设置了【x:string】= string相当于这个接口的字符串索引返回值都是字符串,而y:number违背这一原则,冲突了。反过来 如果定义了【x:string】=Number, 就不能设置 y:string了。
  11. 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。因为 数字索引或转化为字符串索引,而转化的这部分索引对应的值的类型范围 超过了 字符串索引类型的范围,就会报错,相当于超出范围
  12. 一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集

泛型

类型推断

类型兼容性

当一个类型Y可以被赋值给另一个类型X时,我们就可以说类型X兼容类型Y。

X 兼容 Y:X(目标类型) = Y(源类型)

源类型必须具备目标类型的所有属性。

结构之间兼容:成员少的兼容成员多的
函数之间兼容:参数多的兼容参数少的

类型保护

typescript 能够在特定的区块中保证变量属于某种确定的类型,可以在此区块中放心的引用此类型的属性,或者调用此类型的方法。

类型保护方法:

  1. 使用instanceof 可以判断一个实例是不是属于某个类
  2. 使用in 可以判断一个属性是不是属于某个对象
  3. 使用 typeof 可以判断一个基本类型
  4. 类型保护函数:某些判断可能不是一条语句能够搞定的,需要更多复杂的逻辑,适合封装到一个函数内

高级类型:交叉类型和联合类型

ts为了保障语言的灵活性而引入的类型:交叉类型和联合类型

交叉类型是取所有类型的并集,使用 & 符。比较适合做类型的混入

联合类型使用 | 符,具有不确定性,可以增强代码的灵活性

可区分的联合类型:利用两个类型的共有属性建立类型保护区块。

高级类型:索引类型

keyof T

interface obj {
a: number,
b: string
}

let key: keyof T

这时key的类型将变为number:string

T[K]

let value: Obj['a']

这时value的类型就是number类型

T extends U


function getValues<T, K extends keyof T>(obj: T,keys: K[]): T[k]{

}

索引类型可以实现对对象属性的查询和访问,再配合泛型约束就可以使我们建立对象、对象属性以及属性值之间的约束关系。

映射类型

从旧类型中创建新类型的一种方式。新的类型以相同的形式去转换旧的类型,比如可以令每个属性成为readonly或者可选的。

Readonly:只读

Partial:可选

条件类型

由条件表达式所决定的类型:T extends U ? X : Y,含义是:如果类型T可以被赋值为U,那么结果类型就是X,否则就是Y。

工程篇

TypeScript 工具体系分为 babel系和非babel系

TypeScript 工具体系

实战

  1. 定义组件继承:class componentName extends Component<componentNameProps, componentNameState> {}
  2. 定义props 数据类型
  3. 定义state 数据类型