沉梦手记 沉梦手记
首页
  • 基础篇
  • 集合篇
  • 并发篇
  • JVM
  • 新特性
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 数据库基础
  • MySql
  • Redis
  • 达梦数据库
  • Spring
  • SpringBoot
  • Mybatis
  • Shiro
  • 设计须知
  • UML画图
  • 权限校验
  • 设计模式
  • API网关
  • 网络通信
  • 消息队列
  • SpringCloud
  • 分布式事务
  • 云存储
  • 搜索引擎
  • 前端基础
  • Vue
  • React
  • 开发工具篇
  • 工具库篇
  • 开发技巧篇
  • 工具类系列
  • 运维与部署
  • 音视频处理
  • 随笔
  • 博客搭建
  • 网站收藏箱
  • 断墨寻径摘录
  • 费曼学习法
Github (opens new window)

沉梦听雨

时间是最好的浸渍剂,而沉淀是最好的提纯器🚀
首页
  • 基础篇
  • 集合篇
  • 并发篇
  • JVM
  • 新特性
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 数据库基础
  • MySql
  • Redis
  • 达梦数据库
  • Spring
  • SpringBoot
  • Mybatis
  • Shiro
  • 设计须知
  • UML画图
  • 权限校验
  • 设计模式
  • API网关
  • 网络通信
  • 消息队列
  • SpringCloud
  • 分布式事务
  • 云存储
  • 搜索引擎
  • 前端基础
  • Vue
  • React
  • 开发工具篇
  • 工具库篇
  • 开发技巧篇
  • 工具类系列
  • 运维与部署
  • 音视频处理
  • 随笔
  • 博客搭建
  • 网站收藏箱
  • 断墨寻径摘录
  • 费曼学习法
Github (opens new window)
  • 前端基础

  • Vue

    • Vue-Router入门
    • Pinia入门
    • Vue3入门

      • Vue3简介与环境搭建
      • TypeScript基础
        • 1. TypeScript
          • 1) 动态类型的问题
          • 2) 入门
          • 3) 类型
          • 标注位置
          • 标注变量
          • 标注参数
          • 标注返回值
          • 复杂类型
          • type
          • interface
          • 可选属性
          • 鸭子类型
          • 方法类型
          • 字面量类型
          • nullish 类型
          • 泛型
          • 4) 意义
          • 更好理解框架
          • 更好的提示
          • 5) 类
          • 基本语法
          • 只读属性
          • 方法
          • get,set
          • 类与接口
          • 继承与接口
          • 方法重写
      • 模板语法与指令
      • 计算属性与侦听器
      • 事件处理与表单输入
      • 组件与响应式API
      • 网络请求
      • UI组件库与项目实战
    • Vue3进阶
  • React

  • 前端学习
  • Vue
  • Vue3入门
沉梦听雨
2023-07-07
目录

TypeScript基础

# TypeScript基础

Vue3 使用 TypeScript 重构了大量代码,学习 Vue3 前有必要了解 TypeScript 的基础知识。

# 1. TypeScript

# 1) 动态类型的问题

前面我们讲过 js 属于动态类型语言,例如

function test(obj) {    
}
1
2

obj 可能只是个字符串

test('hello, world')
1

obj 也有可能是个函数

test(()=>console.log('hello, world'))
1

obj 类型不确定,就给后期使用者带来了麻烦,一旦参数传不对,代码就崩溃了

动态类型意味着

  • 运行代码时才知道发生什么 (running the code to see what happens)

静态类型意味着

  • 在代码运行前,就对它的行为做出预测 (make predications about what code is expected before it runs)

下面的 typescript 代码,就在代码运行前对参数加入了约束限制

function test(msg : string) {
}
1
2
  • 限制了参数只能做 string 那些事
function test(msg : Function) {
  msg()
}
1
2
3
  • 限制了参数只能做函数那些事

# 2) 入门

安装 typescript 编译器

npm install -g typescript
1

编写 ts 代码

function hello(msg: string) {
  console.log(msg)
}

hello('hello,world')
1
2
3
4
5

执行 tsc 编译命令

tsc xxx.ts
1

编译生成 js 代码,编译后进行了类型擦除

function hello(msg) {
    console.log(msg);
}
hello('hello,world');
1
2
3
4

再来一个例子,用 interface 定义用户类型

interface User {
  name: 沉梦听雨
  age: number
}

function test(u: User): void {
  console.log(u.name)
  console.log(u.age)
}

test({ name: 'zhangs', age: 18 })
1
2
3
4
5
6
7
8
9
10
11

编译后

function test(u) {
    console.log(u.name);
    console.log(u.age);
}
test({ name: 'zhangs', age: 18 });
1
2
3
4
5

可见,typescript 属于编译时实施类型检查(静态类型)的技术

# 3) 类型

类型 例 备注
字符串类型 string
数字类型 number
布尔类型 boolean
数组类型 number[],string[],boolean[] 依此类推
任意类型 any 相当于又回到了没有类型的时代
复杂类型 type 与 interface
函数类型 () => void 对函数的参数和返回值进行说明
字面量类型 "a"|"b"|"c" 限制变量或参数的取值
nullish类型 null 与 undefined
泛型 <T>,<T extends 父类型>

# 标注位置

# 标注变量
let message: string = 'hello,world'
1
  • 一般可以省略,因为可以根据后面的字面量推断出前面变量类型
let message = 'hello,world'
1
# 标注参数
function greet(name: string) {
    
}
1
2
3

很多时候,都能够推断出参数类型

const names = ['Alice', 'Bob', 'Eve']
const lowercaseNames = names.map((e: string) => e.toLowerCase())
1
2
  • 可以用类型推断,推断出 e 是 string 类型
# 标注返回值
function add(a: number, b: number) : number {
    return a + b
}
1
2
3
  • 一般也可以省略,因为可以根据返回值做类型推断

# 复杂类型

# type
type Cat = {
  name: 沉梦听雨
  age: number
}

const c1: Cat = { name: '小白', age: 1 }
const c2: Cat = { name: '小花' }					  // 错误: 缺少 age 属性
const c3: Cat = { name: '小黑', age: 1, sex: '公' } // 错误: 多出 sex 属性
1
2
3
4
5
6
7
8
# interface
interface Cat {
  name: 沉梦听雨
  age: number
}

const c1: Cat = { name: '小白', age: 1 }
const c2: Cat = { name: '小花' }					  // 错误: 缺少 age 属性
const c3: Cat = { name: '小黑', age: 1, sex: '公' } // 错误: 多出 sex 属性
1
2
3
4
5
6
7
8
# 可选属性

如果需要某个属性可选,可以用下面的语法

interface Cat {
  name: 沉梦听雨
  age?: number
}

const c1: Cat = { name: '小白', age: 1 }
const c2: Cat = { name: '小花' }					  // 正确: age 属性可选
1
2
3
4
5
6
7
  • 可选属性要注意处理 undefined 值
# 鸭子类型
interface Cat {
  name: 沉梦听雨
}

function test(cat: Cat) {
  console.log(cat.name)
}

const c1 = { name: '小白', age: 1 } 
test(c1)
1
2
3
4
5
6
7
8
9
10
  • const c1 并没有声明类型为 Cat,但它与 Cat 类型有一样的属性,也可以被当作是 Cat 类型

# 方法类型

interface Api {
  foo(): void,
  bar(str: string): string
}

function test(api: Api) {
  api.foo()
  console.log(api.bar('hello'))
}

test({
  foo() { console.log('ok') },
  bar(str: string) { return str.toUpperCase() }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 字面量类型

function printText(s: string, alignment: "left" | "right" | "center") {
  console.log(s, alignment)
}

printText('hello', 'left')
printText('hello', 'aaa') // 错误: 取值只能是 left | right | center
1
2
3
4
5
6

# nullish 类型

function test(x?: string | null) {
  console.log(x?.toUpperCase())
}

test('aaa')
test(null)
test()
1
2
3
4
5
6
7
  • x?: string | null 表示可能是 undefined 或者是 string 或者是 null

# 泛型

下面的几个类型声明显然有一定的相似性

interface RefString {
  value: string
}

interface RefNumber {
  value: number
}

interface RefBoolean {
  value: boolean
}

const r1: RefString = { value: 'hello' }
const r2: RefNumber = { value: 123 }
const r3: RefBoolean = { value: true }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

可以改进为

interface Ref<T> {
  value: T
}

const r1: Ref<string> = { value: 'hello' }
const r2: Ref<number> = { value: 123 }
const r3: Ref<boolean> = { value: true }
1
2
3
4
5
6
7
  • 泛型的要点就是 <类型参数>,把【类型】也当作一个变化的要素,像参数一样传递过来,这样就可以派生出结构相似的新类型

函数定义也支持泛型

function ref<T>(n: T): Ref<T> {
  return { value: n }
}

const v1 = ref("hello"); 	// Ref<string>
const v2 = ref(123.3333);	// Ref<number>

v1.value.toLocaleLowerCase()
v2.value.toFixed(2)
1
2
3
4
5
6
7
8
9

# 4) 意义

# 更好理解框架

现在越来越多的前端框架采用 typescript,如果懂 typescript 语法,可以更好地阅读框架代码

以 Map 为例

const map = new Map<string, string>()
map
  .set("a", "b")
  .set("c", "d")

map.forEach((value,key,m)=>{
  console.log(value, key)
})
1
2
3
4
5
6
7
8
  • 注意编译需要 tsc --target es6 .\xxx.ts

# 更好的提示

例如,从服务器返回的一段 json,如果不用 typescript,则编辑器也不能给出准确的提示

interface User {
  name: 沉梦听雨
  age: number
}

const user: User = JSON.parse(`{ "name":"张三", "age":18 }`)
1
2
3
4
5
6

# 5) 类

关于 TypeScript 与 JavaScript 中的类语法不是重点,class 相关语法只是起到辅助作用,更重要的是前面讲的 interface

# 基本语法

class User {
    name: 沉梦听雨
    
    constructor(name: string) {
        this.name = name
    }
}

const u = new User('张三')
1
2
3
4
5
6
7
8
9

其实会被编译成这个样子(默认 --target=es3)

var User = /** @class */ (function () {
    function User(name) {
        this.name = name;
    }
    return User;
}());
var u = new User('张三');
1
2
3
4
5
6
7

所以 js 中的 class,并不等价于 java 中的 class,它还是基于原型实现的,原理参考第二章(036、037)

# 只读属性

class User {
  readonly name: string;
  
  constructor(name: string) {
      this.name = name
  }
}

const u = new User('张三')
u.name = '李四'				// 编译错误
1
2
3
4
5
6
7
8
9
10
  • readonly 是 typescript 特有的,表示该属性只读

# 方法

class User {
  readonly name: string;
  
  constructor(name: string) {
      this.name = name
  }

  study() {
    console.log(`[${this.name}]正在学习`)
  }
}

const u = new User('张三')
u.study()
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# get,set

class User {
  _name: string;

  constructor(name: string) {
    this._name = name
  }

  get name() {
    return this._name
  }

  set name(name: string) {
    this._name = name
  }
}

const u = new User('张三')
console.log(u.name)
u.name = '李四'
console.log(u.name)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  • 注意,需要在编译时加上 tsc --target es6 .\xxx.ts 选项
  • es6 等价于 es2015,再此之上还有 es2016 ... es2022

# 类与接口

interface User {
  name: 沉梦听雨
  study(course: string): void
}

class UserImpl implements User {
  name: 沉梦听雨
  constructor(name: string) {
    this.name = name
  }
  study(course: string) {
    console.log(`[${this.name}]正在学习[${course}]`)
  }
  foo() { }
}

const user: User = new UserImpl('张三')
user.study('Typescript')
user.foo() // 错误,必须是接口中定义的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 继承与接口

interface Flyable {
  fly(): void
}

class Animal {
  name: 沉梦听雨
  constructor(name: string) {
    this.name = name
  }
}

class Bird extends Animal implements Flyable {
  fly() {
    console.log(`${this.name}在飞翔`)
  }
}

const b: Flyable & Animal = new Bird("小花")
b.fly()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  • Flyable & Animal 表示变量是 flyable 类型,同时也是 Animal 类型

# 方法重写

class Father {
  study(): void {
    console.log(`father study`)
  }
}

class Son extends Father {  
  study(): void {
    super.study()
    console.log(`son study`)
  }
}

const f: Father = new Son()
f.study()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
上次更新: 2026/11/5 11:56:09
Vue3简介与环境搭建
模板语法与指令

← Vue3简介与环境搭建 模板语法与指令→

Theme by Vdoing | Copyright © 2023-2026 沉梦听雨 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式