TypeScript学习
文档
文档说明
- 学习地址
- 快速上手
- 代码测试
- 安装
1 2 3
| >npm install -g typescript 安装 >tsc -v 查看版本Version 4.6.4 >tsc --init 生成tsconfig.json配置文件
|
开始
编译
新建ts文件
src/helloworld.ts
1 2 3 4 5
| function greeter (person) { return 'Hello, ' + person } let user = 'Yee' console.log(greeter(user))
|
>tsc helloworld.ts
编译
>node helloworld.js
运行
hello,Yee
打印
vscode自动编译
1 2 3 4 5 6 7
| 1). 生成配置文件tsconfig.json tsc --init 2). 修改tsconfig.json配置 "outDir": "./js", "strict": false, 3). 启动监视任务: 终端 -> 运行任务 -> 监视tsconfig.json
|
终端任务重用

如果还是失败,vscode编辑器要选择默认终端
配置中文提示
配送搜索 typescript local 设置成zh-CN
编译选项
基础类型
> 基本语法
let 变量名: 数据类型 = 值
1 2 3 4
| let a2: number = 0b1010
|
数组类型
语法:
let 变量名: 数据类型[] = [值1,值2,值3]
语法:
let 变量名: Array<数据类型> = [值1,值2,值3]
1 2
| let arr1: number[] = [10, 20, 30, 40, 50] let arr2: Array<number> = [100, 200, 300]
|
枚举类型
枚举里面的每个数据值都可以叫元素,每个元素都有自己的编号,编号是从0开始的,依次的递增加1
1 2 3 4 5 6 7 8 9 10
| enum Color { red = 1, green, blue } let color: Color = Color.red console.log(color) console.log(Color.red, Color.green, Color.blue) console.log(Color[3])
|
void 类型
在函数声明的时候,小括号的后面使用:void,代表的是该函数没有任何的返回值
1 2 3 4 5 6 7
| function showMsg(): void { console.log('你好') return null } console.log(showMsg())
|
object 类型
定义一个函数,参数是object类型,返回值也是object类型
1 2 3 4 5 6 7 8 9 10 11
| function getObj(obj: object): object { console.log(obj) return { name: '卡卡西', age: 27 } } console.log(getObj(String))
|
联合类型,类型断言,类型推断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
function getLength(x: number | string) { if ((x as string).length) { return (x as string).length } else { return x.toString().length } } console.log(getLength('abcd'), getLength(1234))
|
接口
接口是对象的状态(属性)和行为(方法)的抽象(描述)
接口:是一种类型,是一种规范,是一种规则,是一个能力,是一种约束
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
| interface IPerson { readonly id: number name: string age: number sex?: string
[proppName:string]:any; } const person: IPerson = { id: 1, name: '小甜甜', age: 18, } console.log(person) person.sex='女' console.log(person)
|
函数类型
为了使用接口表示函数类型,我们需要给接口定义一个调用签名。
它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| interface ISearchFunc { (source: string, subString: string): boolean } const searchString: ISearchFunc = function (source: string, subString: string): boolean { return source.search(subString) > -1 } console.log(searchString('哈哈,我又变帅了', '帅'))
|
类类型(约束)
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| interface IFly { fly:Function } class Person implements IFly { fly() { console.log('我会飞了,我是超人') } } const person = new Person() person.fly() interface ISwim { swim:Function } class Person2 implements IFly, ISwim { fly() { console.log('我飞了2') } swim() { console.log('我会游泳啦2') } } const person2 = new Person2() person2.fly() person2.swim() interface IMyFlyAndSwim extends IFly, ISwim { } class Person3 implements IMyFlyAndSwim { fly() { console.log('我飞了3') } swim() { console.log('我会游泳啦3') } } const person3 = new Person3() person3.fly() person3.swim()
|
类
建一个 User 类,它带有一个构造函数和一些公共字段。因为类的字段包含了接口所需要的字段,所以他们能很好的兼容。
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
|
class User { 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('Yee', 'Huang')
console.log(greeter(user))
|
继承
继承:类与类之间的关系
继承后类与类之间的叫法:
A类继承了B这个类,那么此时A类叫子类,B类叫基类
子类—->派生类
基类—->超类(父类)
一旦发生了继承的关系,就出现了父子类的关系(叫法)
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 35 36 37 38 39 40 41 42 43 44
| class Person { name: string age: number gender: string constructor(name: string='小明', age: number=18, gender: string='男') { this.name = name this.age = age this.gender = gender } sayHi(str: string) { console.log(`我是:${this.name},${str}`) } } class Student extends Person { constructor(name: string, age: number, gender: string) { super(name, age, gender) } sayHi() { console.log('我是学生类中的sayHi方法') super.sayHi('哈哈') } } const person = new Person('大明明',89,'男') person.sayHi('嘎嘎') const stu = new Student('小甜甜',16,'女') stu.sayHi()
|
多态
多态:父类型的引用指向了子类型的对象,不同类型的对象针对相同的方法,产生了不同的行为
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| class Animal { name: string constructor(name: string) { this.name = name } run(distance: number = 0) { console.log(`跑了${distance} 米这么远的距离`, this.name) } } class Dog extends Animal { constructor(name: string) { super(name) } run(distance: number = 5) { console.log(`跑了${distance} 米这么远的距离`, this.name) } } class Pig extends Animal { constructor(name: string) { super(name) } run(distance: number = 10) { console.log(`跑了${distance} 米这么远的距离`, this.name) } } const ani: Animal = new Animal('动物') ani.run() const dog: Dog = new Dog('大黄') dog.run() const pig: Pig = new Pig('八戒') pig.run() console.log('===========') const dog1: Animal = new Dog('小黄') dog1.run() const pig1: Animal = new Pig('小猪') pig1.run() console.log('=============') function showRun(ani: Animal) { ani.run() } showRun(dog1) showRun(pig1)
|
修饰符
修饰符(类中的成员的修饰符):主要是描述类中的成员(属性,构造函数,方法)的可访问性
类中的成员都有自己的默认的访问修饰符,public
public修饰符—公共的,类中成员默认的修饰符,代表的是公共的,任何位置都可以访问类中的成员
private修饰符—私有的,类中的成员如果使用private来修饰,那么外部是无法访问这个成员数据的,当然,子类中也是无法访问该成员数据的
protected修饰符—-受保护的,类中的成员如果使用protected来修饰,那么外部是无法访问这个成员数据的,当然,子类中是可以访问该成员数据的
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 35 36 37 38
|
class Person { protected name:string public constructor(name: string) { this.name = name } public eat() { console.log('嗯,这个骨头真好吃', this.name) } } class Student extends Person { constructor(name: string) { super(name) } play() { console.log('我就喜欢玩布娃娃',this.name) } } const per = new Person('大蛇丸') per.eat() const stu = new Student('红豆') stu.play()
|
readonly修饰符
readonly修饰符:首先是一个关键字,对类中的属性成员进行修饰,修饰后,该属性成员,就不能在外部被随意的修改了
构造函数中,可以对只读的属性成员的数据进行修改
如果构造函数中没有任何的参数,类中的属性成员此时已经使用readonly进行修饰了,那么外部也是不能对这个属性值进行更改的
构造函数中的参数可以使用readonly进行修饰,一旦修饰了,那么该类中就有了这个只读的成员属性了,外部可以访问,但是不能修改
构造函数中的参数可以使用public及privte和protected进行修饰,无论是哪个进行修饰,该类中都会自动的添加这么一个属性成员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Person { readonly name: string constructor(name: string = '大甜甜') { this.name = name } sayHi() { console.log('考尼奇瓦', this.name) } } const person: Person = new Person('小甜甜') console.log(person) console.log(person.name) person.name = '大甜甜' console.log(person.name)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Person { constructor(readonly name: string = '大甜甜') { this.name = name } } const person: Person = new Person('小甜甜') console.log(person) person.name = '佐助' console.log(person.name)
|
存储器
存取器:让我们可以有效的控制对 对象中的成员的访问,通过getters和setters来进行操作
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
| class Person { firstName: string lastName: string constructor(firstName: string, lastName: string) { this.firstName = firstName this.lastName = lastName } get fullName() { console.log('get中...') return this.firstName + '_' + this.lastName } set fullName(val) { console.log('set中...') let names = val.split('_') this.firstName = names[0] this.lastName = names[1] } } const person: Person = new Person('东方', '不败') console.log(person) console.log(person.fullName) person.fullName = '诸葛_孔明' console.log(person.fullName)
|
静态成员
静态成员:在类中通过static修饰的属性或者方法,那么就是静态的属性及静态的方法,也称之为:静态成员
静态成员在使用的时候是通过类名.的这种语法来调用的
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
| class Person { static name1: string = '小甜甜' constructor() { } static sayHi() { console.log('萨瓦迪卡') } } console.log(Person.name1) Person.name1 = '佐助' console.log(Person.name1) Person.sayHi()
|
抽象类
抽象类:包含抽象方法(抽象方法一般没有任何的具体内容的实现),也可以包含实例方法,抽象类是不能被实例化,为了让子类进行实例化及实现内部的抽象方法
抽象类的目的或者是作用最终都是为子类服务的
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
| abstract class Animal{ abstract eat() sayHi(){ console.log('您好啊') } } class Dog extends Animal{ eat(){ console.log('舔着吃,真好吃') } } const dog:Dog = new Dog() dog.eat() dog.sayHi()
|
函数
函数:封装了一些重复使用的代码,在需要的时候直接调用即可
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
| function add(x: string, y: string): string { return x + y } const result1: string = add('111', '222') console.log(result1) console.log() const add2 = function (x: number, y: number): number { return x + y } console.log(add2(10, 20)) const add3: (x: number, y: number) => number = function (x: number, y: number): number { return x+y } console.log(add3(10,100))
|
参数
可选参数:函数在声明的时候,内部的参数使用了?进行修饰,那么就表示该参数可以传入也可以不用传入,叫可选参数
默认参数:函数在声明的时候,内部的参数有自己的默认值,此时的这个参数就可以叫默认参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const getFullName = function (firstName: string='东方', lastName?: string): string { if (lastName) { return firstName + '_' + lastName } else { return firstName } } console.log(getFullName()) console.log(getFullName('诸葛')) console.log(getFullName('诸葛','孔明'))
|
1 2 3 4 5 6 7 8 9 10 11 12
|
(() => { function showMsg(str: string,str2:string, ...args: string[]) { console.log(str) console.log(args) } showMsg('a','b','c','d','e') })()
|
函数重载
函数重载:函数名字相同,函数的参数及个数不同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function add(x: string, y: string): string function add(x: number, y: number): number // 函数声明 function add(x: string | number, y: string | number): string | number | undefined { if (typeof x === 'string' && typeof y === 'string') { return x + y // 字符串拼接 } else if (typeof x === 'number' && typeof y === 'number') { return x + y } return } console.log(add('诸葛', '孔明')) console.log(add(10, 20))
|
泛型
在定义函数、接口、类的时候不能预先确定要使用的数据的类型,而是在使用函数、接口、类的时候才能确定数据的类型
1 2 3 4 5 6 7 8 9 10 11 12 13
| function getArr1(value: number, count: number): number[] { const arr: number[] = [] for (let i = 0; i < count; i++) { arr.push(value) } return arr } const arr1 = getArr1(100.123, 3) console.log(arr1)
|
1 2 3 4 5 6 7 8 9 10 11 12
| function getArr2(value: string, count: number): string[] { const arr: string[] = [] for (let i = 0; i < count; i++) { arr.push(value) } return arr } const arr2 = getArr2('abc', 3) console.log(arr2)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function getArr3(value: any, count: number): any[] { const arr: any[] = [] for (let i = 0; i < count; i++) { arr.push(value) } return arr } const arr1 = getArr3(100.123, 3) const arr2 = getArr3('abc', 3) console.log(arr1) console.log(arr2) console.log(arr1[0].toFixed(2)) console.log(arr2[0].split(''))
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function getArr4<T>(value: T, count: number): T[] { const arr: Array<T> = [] for (let i = 0; i < count; i++) { arr.push(value) } return arr } const arr1 = getArr4<number>(200.12345, 5) const arr2 = getArr4<string>('abcdefg', 5) console.log(arr1) console.log(arr2) console.log(arr1[0].toFixed(3)) console.log(arr2[0].split(''))
|
多个参数
1 2 3 4 5 6 7 8 9
|
function getMsg<K, V>(value1: K, value2: V): [K, V] { return [value1, value2] } const arr1 = getMsg<string,number>('jack',100.2345) console.log(arr1[0].split('')) console.log(arr1[1].toFixed(1))
|
泛型接口
在定义接口时, 为接口中的属性或方法定义泛型类型,在使用接口时, 再指定具体的泛型类型
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| interface IBaseCRUD<T> { data: Array<T> add: (t: T) => T getUserId: (id: number) => T | undefined } class User { id?: number name: string age: number constructor(name: string, age: number) { this.name = name this.age = age } } class UserCRUD implements IBaseCRUD<User> { data: Array<User> = [] add(user: User): User { user.id = Date.now() + Math.random() this.data.push(user) return user } getUserId(id:number = 0): User | undefined { return this.data.find(user => user.id === id) } } const userCRUD: UserCRUD = new UserCRUD() userCRUD.add(new User('jack', 20)) userCRUD.add(new User('tom', 25)) const { id } = userCRUD.add(new User('lucy', 23)) userCRUD.add(new User('rousi', 21))
console.log(userCRUD.data) const user = userCRUD.getUserId(id) console.log(user)
|
泛型类
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
|
class GenericNumber<T>{ defaultValue: T| undefined add: ((x: T,y: T) => T)| undefined } const g1: GenericNumber<number> = new GenericNumber<number>() g1.defaultValue = 100 g1.add = function (x, y) { return x + y } console.log(g1.add(g1.defaultValue,20)) const g2: GenericNumber<string> = new GenericNumber<string>() g2.defaultValue = '哈哈' g2.add = function (x, y) { return x + y } console.log(g2.add('帅杨',g2.defaultValue))
|
泛型约束
如果我们直接对一个泛型参数取 length 属性, 会报错, 因为这个泛型根本就不知道它有这个属性
1 2 3 4 5 6 7 8 9 10 11 12
| interface ILength{ length:number } function getLength<T extends ILength>(x: T): number { return x.length } console.log(getLength<string>('what are you no sha lei'))
|