TypeScript笔记

1. 安装

输入命令:npm install -g typescript进行全局安装typescript,运行tsc -V查看typescript的版本,以及验证是否安装成功。

1.1 编写一个typescript文件

我们简单的编写一个typescript类型的文件greeter.ts,文件的后缀为ts,内容如下(纯js代码):

function greeter (person) {
    return 'Hello' + person
}

let user = 'typescript'
console.log(greeter(user))

然后在cmd终端运行命令:tsc greeter.tstypescript文件转换为浏览器可以识别的ts代码;执行完之后会看对目录中会出现一个同名的后缀为js的文件,这个就是抓换的文件。

上面的代码我们修改一下:

function greeter (person:string) {
    return 'Hello' + person
}

let user = [1, 2]
console.log(greeter(user))

如果你的编译器里面安装了ypescript的插件会直接提示错误,我们再次终端运行命令:tsc greeter.ts会发现报错提示,类型不匹配,上面的代码意思是我们接收的一个参数为string类型的,但是我们传入的参数是一个数组,因此会提示错误,但是还是可以编译成功的。如果一个函数只需要一个参数,但是我们传入两个参数,也是会报错的:

function greeter (person:string) {
    return 'Hello' + person
}

let user = 'typescript'
console.log(greeter(user, 'java'))

typescript中使用interface关键字定义一个接口,代码如下:

// 定义一个接口,相当于定义一个对象
interface Person {
    firstName: string
    lastName: string
}
// 对传入的参数进行类型检验,是一个Person对象
function greeter (person:Person) {
    return 'Hello' + person.firstName + '' + person.lastName
}
// 构造参数对象
let user: Person = {
    firstName: 'typescript',
    lastName: 'java'
}
console.log(greeter(user))

还是使用clss关键字,具体代码如下:代码很简单。

class User {
    // 全局变量,默认public
    fullName:string
    firstName: string
    lastName: string

    constructor(firstName: string, lastName: string) {
        this.firstName = firstName
        this.lastName = lastName
        this.fullName = firstName + ' ' + lastName
    }
}

interface Person {
    firstName: string
    lastName: string
}

function greeter (person:Person) {
    return 'Hello' + person.firstName + '' + person.lastName
}
// 接口跟类的类型一样。
let user = new User('typescript', 'java')
console.log(greeter(user))
2. typescript 的类型系统
2.1 基础类型
2.2 变量声明

在进行变量的限制的时候,我们会使用?:来限制参数,?:是代表可选参数和可选属性;使用了–strictNullChecks也就是加了?:可选参数会被自动加上|undefined,如下面的代码:

function f(x: number, y?: number) {
    return x + (y || 0);
}
f(1, 2);
f(1);
f(1, undefined);
f(1, null); // error, 'null' is not assignable to 'number | undefined'
// -------------------------
class C {
    a: number;
    b?: number;
}
let c = new C();
c.a = 12;
c.a = undefined; // error, 'undefined' is not assignable to 'number'
c.b = 13;
c.b = undefined; // ok
c.b = null; // error, 'null' is not assignable to 'number | undefined'
2.3 接口

接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。给函数传入参数的时候我们使用接口的可选属性,接口的定义也一般用作对函数传入参数的类型进行限定。如下代码:

interface SquareConfig {
interface Square {
  color: string,
  area: number
}

interface SquareConfig {
  color?: string
  width?: number
}

function createSquare (config: SquareConfig): Square {
  let newSquare = {color: 'white', area: 100}
  if (config.color) {
    newSquare.color = config.color
  }
  if (config.width) {
    newSquare.area = config.width * config.width
  }
  return newSquare
}

let mySquare = createSquare({color: 'black'})
}

带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个? 符号。可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。

2.3.1 只读属性

对于属性的话,定义只读属性如下:

interface Point {
  readonly x: number
  readonly y: number
}
// --------
let p1: Point = { x: 10, y: 20 }
p1.x = 5 // error!

定义数组是只读的,如下:

let a: number[] = [1, 2, 3, 4]
let ro: ReadonlyArray<number> = a
ro[0] = 12 // error!
ro.push(5) // error!
ro.length = 100 // error!
a = ro // error!

对于readonlyconst的使用:如果是变量的话,一般我们是使用const定义,如果是属性的话,我们一般是使用readonly去定义。

2.3.2 字符串索引签名

我们在写代码的时候经常会遇到下面的情况:

interface SquareConfig {
    color?: string;
    width?: number;
}

function createSquare (config: SquareConfig): { color: string; area: number } {
  let newSquare = {color: 'white', area: 100}
  if (config.color) {
    newSquare.color = config.color
  }
  if (config.width) {
    newSquare.area = config.width * config.width
  }
  return newSquare
}

// error: 'colour' 不存在于类型 'SquareConfig' 中
let mySquare = createSquare({ colour: 'red', width: 100 })

绕开这些检查非常简单。 最简便的方法是使用类型断言:

let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig)

然而,最佳的方式是能够添加一个字符串索引签名,前提是你能够确定这个对象可能具有某些做为特殊用途使用的额外属性。 如果 SquareConfig带有上面定义的类型的colorwidth 属性,并且还会带有任意数量的其它属性,那么我们可以这样定义它:

interface SquareConfig {
  color?: string
  width?: number
  [propName: string]: any
}

也可以将要赋值的参数赋值给另一个变量,来绕过这种检查:

let squareOptions = { colour: 'red', width: 100 }
let mySquare = createSquare(squareOptions)
2.3.3 类实现一个接口

当一个类实现了一个接口时,只对其实例部分进行类型检查。constructor 存在于类的静态部分,所以不在检查的范围内。

interface ClockConstructor {
  new (hour: number, minute: number)
}

// error
class Clock implements ClockConstructor {
  currentTime: Date
  constructor(h: number, m: number) { }
}

这里因为当一个类实现了一个接口时,只对其实例部分进行类型检查。constructor存在于类的静态部分,所以不在检查的范围内。

2.3.4 混合类型

接口能够描述 JavaScript 里丰富的类型。 因为 JavaScript 其动态灵活的特点,有时你会希望一个对象可以同时具有上面提到的多种类型。

一个例子就是,一个对象可以同时做为函数和对象使用,并带有额外的属性。

interface Counter {
  (start: number): string
  interval: number
  reset(): void
}

function getCounter(): Counter {
  let counter = (function (start: number) { }) as Counter
  counter.interval = 123
  counter.reset = function () { }
  return counter
}

let c = getCounter()
c(10)
c.reset()
c.interval = 5.0

在使用JavaScript第三方库的时候,你可能需要像上面那样去完整地定义类型

2.3.5 接口继承类

当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 就好像接口声明了所有类中存在的成员,但并没有提供具体实现一样。 接口同样会继承到类的 privateprotected 成员。 这意味着当你创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)。

当你有一个庞大的继承结构时这很有用,但要指出的是你的代码只在子类拥有特定属性时起作用。 这个子类除了继承至基类外与基类没有任何关系。例:

class Control {
  private state: any
}

interface SelectableControl extends Control {
  select(): void
}

class Button extends Control implements SelectableControl {
  select() { }
}

class TextBox extends Control {
  select() { }
}

// Error:“ImageC”类型缺少“state”属性。
class ImageC implements SelectableControl {
  select() { }
}

在上面的例子里,SelectableControl 包含了 Control 的所有成员,包括私有成员 state。 因为 state 是私有成员,所以只能够是 Control 的子类们才能实现 SelectableControl 接口。 因为只有 Control 的子类才能够拥有一个声明于Control 的私有成员 state,这对私有成员的兼容性是必需的。

Control 类内部,是允许通过 SelectableControl 的实例来访问私有成员 state 的。 实际上,SelectableControl 接口和拥有 select 方法的 Control 类是一样的。ButtonTextBox 类是 SelectableControl 的子类(因为它们都继承自Control 并有 select 方法),但 ImageC 类并不是这样的。

2.4 类
2.5 函数
2.6 泛型
2.7 最佳通用类型以及上下文类型
2.8 高级类型
3. 实战 ts-axios 项目构建
3.1 初始化项目
3.2 编写基础请求代码
4. 实战 ts-axios 基础功能实现
4.1 处理请求url参数
4.2 处理请求body数据
4.3 处理请求 header
4.4 获取响应数据
4.5 处理响应 header - 需求分析+ parseHeaders 函数实现及应用
4.6 处理响应 data - 需求分析+ transformResponse 函数实现及应用
5. 实战 ts-axios 异常情况处理
5.1 错误处理
5.2 错误信息增强 -
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jiegiser#

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值