1. TypeScript 简介
TypeScript
由**微软开发,是基于JavaScript
的一个扩展语言**。
TypeScript
包含了JavaScript
的所有内容,即:TypeScript
是JavaScript
的**超集**。
TypeScript
增加了:静态类型检查、接口、 泛型等很多**现代开发特性,更适合大型项目**的开发。
TypeScript
需要**编译**为JavaScript
,然后交给浏览器或其他JavaScript
运行环境执行。
2.为何需要 TypeScript
2.1 今非昔比的 JavaScript(了解)
- JavaScript 当年诞生时的定位是浏览器**脚本语言,用于在网页中嵌入简单的逻辑**,且代码量很少。
- 随着时间的推移,JavaScript 变得越来越流行,如今的 JavaScript 已经可以全栈编程
- 现如今的 JavaScript <应用场景比当年丰富的多,代码量也比当年大很多,随便一个 JavaScript 项目的代码量,可以轻松的达到几万行,甚至十几万行!
- 然而当年 JavaScript出生简陋, 没考虑到如今的应用场景和代码量,逐渐就出现了很多困扰
2.2 JavaScript 中的困扰
1 2
| let welcome = 'hello' welcome()
|
1 2 3 4 5 6 7
| const str = Date.now() % 2 ? '奇数' : '偶数' if (str !== '奇数') { alert('hello') } else if (str === '偶数') { alert('world') } --- 逻辑异常 else if中的数据永远不能执行
|
1 2 3
| const obj = { width: 10, height: 15 }; const area = obj.width * obj.heigth; --- 字母错误 也不会提示
|
1 2 3
| const message = 'hello,world' message.toUperCase() --- toUperCase()不是一个函数 缺少字母p toUpperCase()
|
2.3 静态类型检查
- 在代码运行前进行检查,发现代码的错误或不合理之处,减小运行时出现异常的几率,此种检查叫『静态类型检查』,TypeScript 和核心就是『静态类型检查』,简言之就是**把运行时的错误前置**。
- 同样的功能,TypeScript 的代码量要**大于** JavaScript,但由于 TypeScript 的代码结构更加清晰,在后期代码的维护中 TypeScript 却**胜于 **JavaScript。
3. 创建TS项目
- 输入项目名称
xxxx
选择vue
框架 选择typeScript

1 2
| cd xxxxx项目名称 npm install
|
- 编辑 tsconfig.json 可以修改ts默认配置

4. 类型声明
4.1 基本类型使用
1 2 3 4 5 6 7 8 9 10 11 12
| let a: string let b: number let c: boolean
a = 'hello' a = 100
b = 666 b = '你好'
c = true c = 666
|
4.2 字面量赋值(了解)
1 2 3 4 5
| let a: '你好' let b: 100
a = '欢迎' b = 200
|
4.3 类型推断
TS
会根据我们的代码,进行类型推导,例如下面代码中的变量d
,只能存储数字
但要注意,类型推断不是万能的,面对复杂类型时推断容易出问题,所以尽量还是明确的编写类型声明!
5 数据类型介绍
5.1 JavaScript中的数据类型
string
字符串
number
数值型
boolean
布尔类型
null
空
undefined
未定义
bigint
长整型
symbol
Symbol 是 ES6 新增的一种原始数据类型,它的字面意思是:符号、标记。代表独一无二的值 。
object
:其中object包含:Array、Function、Date、Error等
5.2 TypeScript中的数据类型
- 包含上述8种数据类型
- 包括6种新数据类型
any
任意数据类型
unknown
未知类型
never
不能有值
void
函数不能返回任何值
tuple
元组: 特殊数组类型
enum
枚举类型
- 2种自定义类型
type
定义任意类型
interface
定义接口
在JavaScript中的这些内置构造函数:Number、String、Boolean,用于创建对应的包装对象, 在日常开发时很少使用,在TypeScript中也是同理,所以在TypeScript中进行类型声明时,通常都是用小写的number、string、boolean
6. 数据类型解析
6.1 any
any
的含义是:任意类型,一旦将变量类型限制为any
,那就意味着**放弃了**对该变量的类型检查。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| let a: any
a = 100
a = "你好"
a = null
a = undefined
a = false
let b
b = 100
b = "str"
b = true
|
注意事项:
1 2 3 4 5 6 7 8 9 10
| let aa: any
aa = 100
let bb: string
bb = aa
|
6.2 unknown
1.unknown
的含义是:未知类型,适用于:起初不确定数据的具体类型,要后期才能确定
2.unknown
会强制开发者在使用之前进行类型检查,从而提供更强的类型安全性。
1 2 3 4 5 6 7 8 9 10
| let a: unknown
a = 99 a = '1123123'
a = null let x: number
x = a
|
6.3 never
never
的含义是:任何值都不是,即:不能有值,例如undefined
、null
、''
、0
都不行!
- 几乎不用
never
去直接限制变量,因为没有意义,例如:
1 2 3 4 5 6 7 8
| let a: never
a = 100
a = null
a = undefined
|
1 2 3 4
| function throwError(str: string): never { throw new Error('程序异常退出:' + str) }
|
never
一般是TypeScript
主动推断出来的,例如:
1 2 3 4 5 6 7 8 9 10
| let a: string
a = 'hello'
if (typeof a === 'string') { console.log(a.toUpperCase()) } else { console.log(a) }
|
6.4 void
void
的含义是空,即:函数不返回任何值,调用者也不应依赖其返回值进行**任何操作**!
1 2 3 4 5 6 7 8 9 10 11 12 13
| function add():void { }
function add2():void { return }
function add3():void { return undefined }
|
如果一个函数返回类型为void
,那么:
- 从语法上讲:函数是可以返回
undefined
的,至于显式返回,还是隐式返回,这无所谓!
- 从语义上讲:函数调用者不应关心函数返回的值,也不应依赖返回值进行任何操作!即使我们知道它返回了
undefined
。
6.5 object 对象类型
6.5.1 object用法
object(小写)的含义是:所有非原始类型,可存储:对象、函数、数组等,由于限制的范围比较宽泛,在实际开发中使用的相对较少。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| let a: object
a = {} a = {name:'张三'} a = [1,3,5,7,9] a = function(){} a = new String('123')
let b: object
b = 123
b = "123"
b = null
b = undefined
|
6.5.2 声明对象类型
1 2 3 4 5 6 7 8 9 10 11 12 13
| let person1: {name: string, age: number} let person2: {name: string; age: number}
let person3: {name: string, age?: number}
person1 = {name: "张三", age: 30}
person2 = {name: "李四", age:40}
person3 = {name: "王五"}
person3 = {name: "赵六", age: 50}
|
6.5.3 索引签名
索引签名: 允许定义对象可以具有任意数量的属性,这些属性的键和类型是可变的 常用于:描述类型不确定的属性
1 2 3 4 5 6 7 8 9 10 11 12 13
| let person: { name: string age?: number [key: string]: any }
person = { name:'张三', age:18, gender:'男' }
|
6.5.4 声明函数类型
1 2 3 4 5
| export let sum: (num1:number, num2: number) => number
sum = (x,y) => { return x+y }
|
备注:
- TypeScript 中的
=>
在函数类型声明时表示函数类型,描述其参数类型和返回类型。
- JavaScript 中的
=>
是一种定义函数的语法,是具体的函数实现。
6.5.5 声明数组类型
1 2
| let array1: string[] = ["a","b","c","d"] let array2: Array<string> = ["a","b","c","d"]
|
6.6 tuple
元组(Tuple)
是一种特殊的数组类型,可以存储固定数量的元素,并且每个元素的类型是已知的且可以不同。元组用于精确描述一组值的类型,?
表示可选元素。
1 2 3 4 5 6 7 8
| let arr1: [string,number] = ["张三", 200]
let arr2: [string,number?] = ["张三"]
let arr3: [number,...string[]] = [100,"李四","王五","赵六"]
|
6.7 enum类型
枚举(enum
)可以定义一组命名常量,它能增强代码的可读性,也让代码更好维护。
6.7.1 枚举类型讲解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| export enum Result { SUCCESS, Fail }
export let add = function(msg: Result){ if(msg === Result.SUCCESS){ console.log("业务调用成功") }else if(msg === Result.Fail){ console.log("业务调用失败") }else{ console.log("参数异常") } }
|
6.7.2 字符串枚举
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| export enum Result { SUCCESS = "成功", Fail = "失败" }
export let add = function(msg: Result){ if(msg === Result.SUCCESS){ console.log(Result.SUCCESS) console.log("业务调用成功") }else if(msg === Result.Fail){ console.log("业务调用失败") console.log(Result.Fail) }else{ console.log("参数异常") } }
|
6.7.3 常量枚举
官方描述:常量枚举是一种特殊枚举类型,它使用const
关键字定义,在编译时会被内联,避免生成一些额外的代码。
何为编译时内联?
所谓“内联”其实就是 TypeScript 在编译时,会将枚举成员引用替换为它们的实际值,而不是生成额外的枚举对象。这可以减少生成的 JavaScript 代码量,并提高运行时性能。
案例1: 使用普通枚举的 TypeScript 代码如下:
1 2 3 4 5 6 7
| enum Directions { Up, Down, Left, Right } let x = Directions.Up;
|
1 2 3 4 5 6 7 8 9 10
| "use strict"; var Directions; (function (Directions) { Directions[Directions["Up"] = 0] = "Up"; Directions[Directions["Down"] = 1] = "Down"; Directions[Directions["Left"] = 2] = "Left"; Directions[Directions["Right"] = 3] = "Right"; })(Directions || (Directions = {}));
let x = Directions.Up;
|
常量枚举
1 2 3 4 5 6 7 8
| const enum Directions { Up, Down, Left, Right }
let x = Directions.Up;
|
1 2
| "use strict"; let x = 0 ;
|
6.8 联合类型
联合类型(Union Types)表示取值可以为多种类型中的一种。
1 2 3
| let v1: number | string; v1 = 5211314; v1 = 'iloveyou'
|
6.9 断言
类型断言(Type Assertion)可以告诉编译器,“相信我,我知道自己在干什么,别报错,出了事我负责”。联合类型要有
1 2 3 4
| let PI:number | string = 3.141592653
console.log((PI as number).toFixed(2)) console.log((<number>PI).toFixed(2))
|
6.10 函数
TypeScript 为 JavaScript 函数添加了额外的功能
6.10.1 参数与返回值类型
1 2 3 4 5 6 7 8 9 10 11
| function add1(x: number, y: number): number { return x + y }
let add2 = function(x: number, y: number): number { return x + y }
let add3 = (a: number, b: number): number => { return a * b; }
|
TypeScript 能够根据返回语句自动推断出返回值类型,因此我们通常省略返回值的类型。
6.10.2 可选参数
TypeScript 默认要求函数实参数量要与形参的数量保持一致,不过可以使用『 ?: 』设置参数为可选参数
1 2 3 4
| function slice(str: string, start: number, end ?: number): string{ return 'iloveyou'; }
|
6.10.3 参数默认值
TypeScript 与 JavaScript 一样,允许为参数设置默认值
案例: 为所有的手机添加默认值 ‘86’
1 2 3 4
| function buildPhone(code:string, area : string = '+86'){ return area + code; }
|
7 class类型介绍
7.1 Type类型
type
可以为任意类型创建别名,让代码更简洁、可读性更强,同时能更方便地进行类型复用和扩展。
1 2 3 4 5 6 7
| type user = { id: number; name: string; age: number; }
export let myUser: user = {id:100,name:"张三",age: 300}
|
7.2 Class类型
- 如果需要定义一个类型 方便以后统一使用 建议使用class类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| export class User { id:number; name: string; age: number;
constructor(id:number,name:string,age:number){ this.id = id this.name = name this.age = age }
hello() { console.log("你好:"+this.id + ":" + this.name + ":" + this.age) } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <script setup lang="ts">
import { User } from './ts';
let user1 = new User(100,"张三",300)
console.log(user1)
user1.hello()
</script>
<template> <div> <h1>TS案例测试</h1> </div> </template>
<style scoped>
</style>
|
7.3 extends 关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| export class User { id:number; name: string; age: number;
constructor(id:number,name:string,age:number){ this.id = id this.name = name this.age = age }
hello() { console.log("你好:"+this.id + ":" + this.name + ":" + this.age) } }
export class SystemUser extends User { username: string; password: string;
constructor(id:number,name:string,age:number,username: string, password:string){ super(id,name,age) this.username = username, this.password = password }
hello(){ console.log("你好:"+this.username + ":" + this.password) } }
|
7.4 属性修饰符
- 在JS中也会有访问修饰符, 其中的效果和java中的一致
- 默认类型:
public
修饰符 |
含义 |
具体规则 |
public |
公开的 |
可以被:类内部、**子类、类外部**访问 。 |
protected |
受保护的 |
可以被:类内部、**子类**访问。 |
private |
私有的 |
可以被:**类内部**访问。 |
readonly |
只读属性 |
属性无法修改。 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| export class Person {
public id:number; protected name: string; private readonly age: number;
constructor(id:number,name:string,age:number){ this.id = id this.name = name this.age = age } }
export class student extends Person {
hello(){ console.log("你好"+this.id +":" +this.name + ":" +this.age) } }
let p1 = new Person(100,"李四",200)
console.log(p1.name)
|
7.5 class的简化写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| export class User { id:number; name: string; age: number;
constructor(id:number,name:string,age:number){ this.id = id this.name = name this.age = age } }
export class User2 { constructor(public id:number,public name:string,public age:number){} }
|
7.6 抽象类
- 概述:抽象类是一种**无法被实例化的类,专门用来定义类的结构和行为,类中可以写抽象方法,也可以写具体实现。抽象类主要用来为其派生类提供一个基础结构,要求其派生类必须实现**其中的抽象方法。
- 简记:抽象类**不能实例化,其意义是可以被继承,抽象类里可以有普通方法、也可以有抽象方法**。
1 2 3 4 5 6 7 8 9 10 11 12
| abstract class User { abstract eat(foodName:string):string }
export class myUser extends User { eat(foodName: string): string { return "炒着吃:"+foodName } }
|
7.7 Interface 接口
interface
是一种**定义结构的方式,主要作用是为:类、对象、函数等规定一种契约,这样可以确保代码的一致性和类型安全,但要注意interface
只能定义格式,不能包含任何实现** !
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| interface User { id: number, name:string, age: number, gender? :string
hello():void }
class MyUser implements User {
constructor(public id:number,public name:string,public age:number,public gender:string){} hello(): void { console.log("你好世界") } }
|
接口可以被继承,如果继承接口 则需要实现所有的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| interface User { id: number, name:string, age: number, gender? :string
hello():void }
interface MyUser extends User {
username:string password:string
}
class Person implements MyUser { hello(): void { throw new Error("Method not implemented.") }
constructor(public username:string,public password:string,public id:number,public name:string,public age:number){
} }
|
7.8 泛型
泛型允许我们在定义函数、类或接口时,使用类型参数来表示**未指定的类型,这些参数在具体使用时,才被指定具体的类型**,泛型能让同一段代码适用于多种类型,同时仍然保持类型的安全性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function logData(name:string):void{ console.log("页面代码:"+name) }
logData("你好世界")
function logData2<T>(name:T):void{
console.log("页面代码:"+name) }
logData2(100) logData2("这是泛型参数")
|
1 2 3 4 5 6 7 8
| function logData3<T>(name:T):T{ console.log("这个函数必须要求返回类型返回") return name }
console.log(logData3("张三"))
|
1 2 3 4 5 6
| function logData3<T,R>(data1:T,data2:R): T|R {
return Date.now() % 2 ? data1 : data2 }
logData3(300,400)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| interface ServiceInterface<T> {
id: number, name: string data: T
}
interface Book { bookName: string }
interface User { username: string, password: string }
let myService:ServiceInterface<Book> = { id: 100, name: "张三", data: { bookName: "java从入门到放弃" } }
let myService2:ServiceInterface<User> = { id: 200, name: "李四", data: { username: 'admin', password: 'admin123' } }
|