tsc、TypeScript编译器

在终端安装typescript:

1
npm i typescript -g

安装完成后可以使用tsc命令来执行typescript的相关代码。

1
tsc -v  //查看版本号

在vscode新建一个index.ts,输入一下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let a: string
let b: number
let c: boolean

a = 'hello'
b = 99
c = true

console.log(a, b, c)

function count(x: number, y: number): number {
return x + y
}

let result = count(1, 2)
console.log(result)

let srt1: string

srt1 = 'youxianyu'

console.log(typeof srt1)

直接使用浏览器是不认识的,需要用tsc命令转换为javascript代码:

1
2
tsc --watch //全局转换
tsc --watch index.ts //转换指定.ts

转换后index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"use strict";
let a;
let b;
let c;
a = 'hello';
b = 99;
c = true;
console.log(a, b, c);
function count(x, y) {
return x + y;
}
let result = count(1, 2);
console.log(result);
let srt1;
srt1 = 'youxianyu';
console.log(typeof srt1);

使用index.js

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>index</title>
</head>
<body>
<script type="text/javascript" src="./index.js"></script>
</body>
</html>

成功

常用类型

any

any的含义量:任意类型,一旦将变量类型限制为any,那就意味着放弃了对该变量的类型检查。

1
2
3
4
5
6
7
8
9
10
11
let an: any //显示

an = 91
an = 'hello'
an = false

let as: any //隐式

as = 92
as = 'world'
as = true

注意:any类型的变量,可以赋值给任意类型的变量

unknown

unknown的含义是:未知类型。

1.unknown可以理解为一个类型安全any,适用于:不确定数据的具体类型。

1
2
3
4
5
6
7
8
9
let un: unknown

un = 99
un = false
un = 'hello'

let x: string
x = un //不能将类型“unknown”分配给类型“string”
//但可以进行类型检查

2.unknown会强制开发者在使用之前进行类型检查,从而提供更强的类型安全性。

1
2
3
4
5
6
7
8
9
10
11
12
let un: unknown

un = 99
un = false
un = 'hello'

if (typeof un === 'string') {
x=un
}

x = un as string
x=<string>un

3.读取any类型数据的任何属性都不会报错,而unknown正好与之相反。

never

never的含义是:任何值都不是,简而言之就是不能有值(什么都不行)
1.几乎不用never去直接限制变量,因为没有意义。

1
2
3
4
5
6
7
let a: never

//以下对a的所有赋值都会有警告
a=1
a=true
a=undefined
a=unll

2.never一般是typescript主动推断出来的。

1
2
3
4
5
6
7
8
let a: string
a='hello'

if(typeof a ==== 'string'){
console.log(a.toUpperCase())
}else{
console.log(a)
}

3.never也可用于限制函数的返回值。

1
2
3
function throwError(str: string): never{
throw new Error('程序异常退出'+str)
}

void

void通常用于函数返回值声明,含义【函数不返回任何值,调用者也不应该依赖其返回值进行任何操作】

1
2
3
4
function logMessage(msg: string): void{
console.log(msg)
}
logMessage('youxianyu')

注意:logMessage函数是没有显示返回值的,但会有一个隐式返回值,就是undefined;记:undefined是viod可以接受的一种“空”。

1
2
3
4
5
6
7
8
9
10
11
function logMessage(msg: string): void {
console.log(msg)
}
function logMessage1(msg: string): void {
console.log(msg)
return;
}
function logMessage2(msg: string): void {
console.log(msg)
return undefined
}

总结:若函数返回值类型为void,那么:
1.从语法上讲:函数是可以返回undefined的,至于显示返回,还是隐式返回,这都无所谓!
2.从语义上讲:函数调用者不应关心函数返回的值,也不应依赖返回值进行任何操作及时返回了undefined值。

object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let o: object //a能存储的类型是【非原始类型】

o = {}
o = { name: 'tom' }
o = [1, 35, 453, 23, 3]
o = function () { }
o = new String('123')
class Person { }
o = new Person()

//以下代码,是将【原始类型】赋给a,有警告
a = 1
a = ture
a = 'you'
a = null
a=undefined

Object除了undefined和null的任何值。

声明对象类型

1.实际开发中,限制一般对象,通常使用以下形式。

1
2
3
4
5
6
7
8
let person1: { name: string, age?: number }

let person3: { name: string; age?: number }
let person2: {
name: string,
age?: number
}
person1={name:'tom',age:19}

2.索引签名:允许定义对象可以具有任意数量的属性,这些属性的键和类型是可变的,常用于:描述类型不确定的属性。(具有动态属性的对象)

1
2
3
4
5
6
7
8
9
10
11
let person:{
name:string
age?:number
[key:string]: any
}

person={
name:'youxianyu',
age:18,
gender:'男'
}

声明函数类型

1
2
3
4
let count:(a:number,b:number)=> number
count = function(x,y)=>{
return x+y
}

TypeScript中的=>在函数类型声明表示函数类型,描述其参数类型和返回值类型。
JavaScript中的=>是一种定义函数的语法,是具体的函数实现。
函数类型声明还可以使用L:接口,自定义类型等方式。

声明数组类型

1
2
3
4
5
let arr1:string[]
let arr2:Array<string> //泛型

arr1=['a','b','c']
arr2=['hello','world']

tuple

元组(tuble)是一种特殊的数组类型,可以存储固定数量的元素,并且每个元素类型是已知的且可以不同,元组用于精确描述一组值的类型,?表示可选元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//第一个元素必须是string类型,第二关元素是number类型。
let arr1=[string,number]
//第一个元素必须是number类型,第二个元素是可选的,如果存在,必须是boolean类型。
let arr2=[number,boolean?]
//第一个元素必须是number类型,后面的元素可以是任意数量的string类型。
let arr3=[number,...string[]]

arr1=['hello',123]
arr2=[100,flase]
arr2=[200]
arr3=[100,'hello','world']
arr3=[100]

arr1=['hello',123,false]

enum

枚举(enum)可以定义一组命名常量,他能增强代码的可读性,也让代码更好维护。

如下代码的功能是:根据调用walk时传入的不同参数,执行不同的逻辑,存在的问题是调用walk时传参时没有任何提示,编码者很容易写错字符串内容;并且用于判断逻辑的up、down、left、right是连续且相关的一组值,那此时就特别适合使用枚举(enum)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function walk(str: string) {
if (str === 'up') {
console.log('ok')
} else if (str === 'down') {
console.log('sk')
} else if (str === 'left') {
console.log('kn')
} else if (str === 'right') {
console.log('kn')
}
}

walk('up')
walk('ok')
walk('left')
walk('right')

1.数字枚举
数字枚举一种最常用的枚举类型,其成员的值会自动递增,且数字枚举还具备反向映射的特点,在下面代码的打印中,可以通过只来获取对应的枚举成员名称。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enum Direction{
up,
down,
left,
right
}
function walk(str: Direction) {
if (str === Direction.up) {
console.log('ok')
} else if (str===Direction.down) {
console.log('sk')
} else if () {str===Direction.left
console.log('kn')
} else if (str === Direction.right) {
console.log('kn')
}
}
walk(Direction.down)

2.字符串枚举

1
2
3
4
5
6
7
8
enum pirection{
up='up',
down='down',
left='left',
right='right'
}
let dir:Direction=Direction.up
console.log(dir)

3.常量枚举

1
2
3
4
5
6
7
const enum Directions{
up,
down,
left,
right
}
let x=Directions.up;

type

type可以为任意类型创建别名,让代码更简洁、可读性更强,同时能更方便地进行类型复用和扩展。
1.基本用法
类型别名使用type关键字,type后跟类型名称

1
2
3
type num=number;
let price:num
price=100

2.联合类型
联合类型是一种高级类型,他表示一个值可以是几种不同类型之一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type Status = number | string
type Gender = '男' | '女'

function printstatus(string Status){
console.log(status);
}

function logGender(str:Gender){
console.log(str)
}

printstatus(404)
printstatus('200')
printstatus('501')

logGender('男')
logGender('女')

3.交叉类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
type Area = {
height: number
width:number
}

type Address = {
num: number
cell: number
room:string
}

type House = Area & Address

const house: House = {
height: 100,
width: 120,
num: 3,
cell: 4,
room: '702'
}

复习类相关知识

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{
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
speak() {
console.log(`我叫:${this.name},今年${this.age}岁`)
}
}

const p1 = new Person('YOUXIANYU', 19)
console.log(p1)
p1.speak()
class Student extends Person{
grade: string
constructor(name: string, age: number, grade: string) {
super(name, age)
this.grade=grade
}
study() {
console.log(`${this.name}`)
}
override speak() {
console.log(`我是学生:${this.name},今年${this.age}${this.grade}`)
}
}
const s1 = new Student('youxianyu', 19, '大一')
console.log(s1)
s1.study()
s1.study()

简写

1
2
3
class Person{
constructor(public name:string, public age: number)
}

抽象类

抽象类是一种无法被实例化的类,专门用来定义类的结构和行为,类中可以写抽象方法,也可以写具体实现。抽象类主要用来为其派生类提供一个基础结构,要求其派生类必须实现其中的抽象方法。

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
abstract class Package{
//构造方法
constructor(public weight: number) { }
//抽象方法
abstract calculate(): number
//具体方法
printPackage() {
console.log(`${this.weight},${this.calculate()}`)
}
}

class StandardPackage extends Package{
constructor(weight: number, public unitPrice: number) { super(weight) }
calculate(): number {
return this.weight*this.unitPrice
}
}

class ExpressPackage extends Package{
constructor(weight: number, public unitPrice: number,
public additional: number
) { super(weight) }
calculate(): number {
if (this.weight > 10) {
return 10*this.unitPrice+(this.weight-10)*this.additional
}else{
return this.weight*this.unitPrice
}
}
}
const s2 = new StandardPackage(10, 50)
s2.printPackage()

const s3 = new ExpressPackage(10, 30, 7)
s3.printPackage()

总结:何时使用抽象类
1.定义通用接口:为一组相关的类定义通用的行为(方法或属性)时。
2.提供基础实现:在抽象类中提供某些方法或为其提供基础实现,这样派生类就可以继承这些实现。
3.确保关键实现:强制派生实现一些关键行为。
4.共享代码和逻辑:当多个类需要共享部分代码时,抽象类可以避免代码重复。

interface

定义类结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
interface PersonInterface{
name: string
age: number
speak(n:number):void
}

class Person1 implements PersonInterface{
constructor(public name: string, public age: number) { }
speak(n: number): void {
for (let i = 0; i < n; i++){
console.log(`${this.name},${this.age}`)
}
}
}
const p2 = new Person1('youxianyu', 19)
p2.speak(4)

定义对象结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface UserInterface{
name: string
readonly gender: string
age?: number
run: (n: number) => void
}

const user: UserInterface = {
name: 'you',
gender: '男',
age: 19,
run(n) {
console.log(`${n}`)
}
}

定义函数接口

1
2
3
4
5
6
7
interface CountInterface{
(a: number,b: number): number
}

const count: CountInterface=(x,y)=>{
return x+y
}

泛型

泛型函数

1
2
3
4
5
6
function logData<T>(data: T) {
console.log(data)
}

logData<number>(100)
logData<string>('you')

多个泛型

1
2
3
4
5
6
7
function logData<T,U>(data1: T,data2:U): T | U{
console.log(data1,data2)
return Data.now() % 2 ? data1:data2
}

logData<number,boolean>(100,true)
logData<string,number>('you',666)

泛型接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface PersonInterface<T>{
name: string,
age: number,
extraInfo:T
}

type JobInfo = {
title: string
company:string
}

let p: PersonInterface<JobInfo>={
name:'you',
age: 19,
extraInfo: {
title: '程序员',
company:'加油'

}
}

泛型类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person<T>{
constructor(
public name: string,
public age: number,
public extraInfo: T
) { }
speak() {
console.log(`${this.name}${this.age}`)
console.log(this.extraInfo)
}
}

type JobInfo = {
title: string
company:string
}

const p1 = new Person<JobInfo>('you', 19, {title:'xian',company:'okoko'})

装饰器

类装饰器

基本语法

1
2
3
4
5
6
7
8
9
10
11
12
13
function Demo(target: Function) {
console.log(target)
}

@Demo
class Person{
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age=age
}
}

应用实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function CustomString(target: Function) {
target.prototype.toString = function () {
return JSON.stringify(this)
}
}

@CustomString
class Person{
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age=age
}
}
const p1 = new Person('you', 19)
console.log(p1.toString())

关于构造类型

声明构造类型

1
2
3
type Constructor = new (...args:any[])=>{}
function test(fn:Constructor){}
test(Person)

声明构造类型+指定静态属性