一篇文章轻松学会TypeScript

110 阅读7分钟

安装及自动编译配置

安装
npm i typescript -g

验证安装成功
tsc -v
# 自动编译

1. 生成配置文件`tsc -init`
2. 解除配置项中'outDir'注释
3. 在vscode点击终端->运行任务->typescript->监视tsconfig.json

数据类型

# 布尔类型(boolean)
var demo:boolean = true
# 数字类型(number)
var demo:number = 123
# 字符串类型(string)
var demo:string = '123'
# 数组类型(array)
var demo:number[] = [1,2,3]
var demo:Array<number>= [1,2,3]
# 元组类型(tuple)属于数组的一种
var demo: [number, string, number] = [1, '123', 3] //与类型一一对应
# 枚举类型(enum)
enum demo {
  success = 1,
  error = 0
}
# 任意类型(any)
var demo: any = 324324
# null和undefined
var demo: null =null
# void类型
没有任何类型,一般用于定义方法的时候没有返回值
function fn(): void {
  console.log('无返回值');
  return
}
# never类型
never是其他类型,包括null和undefined的子类型,代表从来不会出现的值,一般不用,可以用any类型去代替

函数

1. `?`可以设置可选项
2. 可选项可以设置默认值
3. 可选项要放在形参的末尾
function fn(name: string, age?: number, sex: string = '男'): string {
  return `姓名${name}年龄${age}性别${sex}`
}
alert(fn('hfd', 18))

在es5中重载下面的函数会覆盖上面的函数,ts中的重载是通过同一个函数接受不同的参数来执行不同的操作。

// es5写法
function demo(name) { }
function demo(name, age) { } // 会覆盖上面的
//ts中函数的重载
function demo(name: string): string
function demo(name: string, age: number): string
function demo(name: string, age?: number): string {
  if (age) {
    return `我的名字:${name},我的年龄${age}`
  } else {
    return `我的名字:${name}`
  }
}
alert(demo('hfd', 18))

// 类
class person {
  public name: string
  constructor(name: string) {
    this.name = name
  }
  run() {
    alert(this.name)
  }
}
var p = new person('张三')
p.run()

//继承(如果子类有和父类相同名称的方法,执行子类的方法)
class web extends person {
  constructor(name: string) {
    super(name)
  }
  run() {
    alert(this.name + '子类')
  }
}
var w = new web('李四')
w.run()
# 修饰符
1. public公有,在当前类、子类、类外都可以访问,不加修饰符默认为public
2. protected保护类型,在当前类里、子类可以访问,类外不可以访问
3. private私有,在类里面可以访问,子类、类外部都不可以访问

静态属性和静态方法

# 静态属性和静态方法
class person {
  name: string
  static age: number = 20
  constructor(name: string) {
    this.name = name
  }
  run() {
    return alert(`${this.name}`)
  }
  static work() {
    // return alert(`${this.name}在工作`) 在ts中静态方法不可以直接访问类里面的属性,需要定义静态属性
    return alert(person.age)

  }
}
person.work()

多态

# 多态(父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现方式)
class animal {
  name: string
  constructor(name: string) {
    this.name = name
  }
  eat() {
    console.log('吃的方法');
  }
}
class dog extends animal {
  constructor(name: string) {
    super(name)
  }
  eat() {
    console.log(this.name + '吃猫粮');
  }
}
class cat extends animal {
  constructor(name: string) {
    super(name)
  }
  eat() {
    console.log(this.name + '吃猫粮');
  }
}
const c = new cat('猫咪')
c.eat()

抽象类

1. ts中的抽象类,提供其他类型继承的基类,不能直接被实例化。
2. 用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在被继承的类中实现。
3. abstract抽象方法只能放在抽象类中
4. 抽象类和抽象方法用来定义标准,如下代码(继承animal的类都需要实现eat方法)
abstract class animal {
  name: string
  constructor(name: string) {
    this.name = name
  }
  abstract eat():any
}
// const a = new animal() // 不可以创建抽象类的实例
class cat extends animal {
  constructor(name: string) {
    super(name)
  }
  // 抽象类的子类必须实现抽象类里的抽象方法
  eat() {
    console.log(this.name + '吃猫粮');
  }
}
const c = new cat('哇卡巴卡')
c.eat()

接口

接口就是行为和动作的规范,对批量的方法进行约束

// 定义接口
interface rule {
  one: string;
  two: number
}
// 使用
class demo {
  name: rule
  constructor(name: rule) { this.name = name }
  run() {
    console.log(this);
    console.log(this.name.one, this.name.two);
  }
}
var d = new demo({ one: '测试', two: 1 })
d.run()

加密函数类型接口

//加密函数类型接口
interface fun {
  (number: string, value: string): string
}
var demo: fun = function (number: string, value: string): string {
  return ''
}

可索引接口

// 可索引接口,对对象或者数组进行约束,下标为string的是对象,下标是number的是数组
interface obj {
  [index: string]: string
}
var demo: obj = { name: '1' }

interface arr {
  [index: number]: number
}
const demo: arr = [1, 2, 3]

类类型接口

// 类类型接口
interface fun {
  eat(food: string): void
  name: string
}
class demo implements fun {
  name: string
  constructor(name: string) {
    this.name = name
  }
  eat(food: string): void {
    console.log(this.name + '爱吃' + food);
  }
}
var d = new demo('小猫咪')
d.eat('小鱼干')

接口继承

// 接口继承
interface animal {
  name: string
  eat(str: string): void
}
// 接口继承接口
interface person extends animal {
  work(str: string): void
}
class demo implements person {
  name: string
  constructor(name: string) {
    this.name = name
  }
  // 使用了接口就需要有接口规定的方法
  eat() { }
  work() { }
}
class ext {
  name: string
  constructor(name: string) {
    this.name = name
  }
  game(game: string) {
    console.log(this.name + '在玩' + game);
  }
}
// 既可以继承类也可以实现接口
class demo2 extends ext implements person {
  constructor(name: string) {
    super(name)
    this.name = name
  }
  eat() { }
  work() { }
}

const d = new demo2('hfd')
d.game('开心消消乐')

泛型

泛型可以帮助我们避免重复的代码,解决了类、方法、接口的复用性,以及对不确定数据类型的支持(类型校验)

// 泛型函数
function fn<T>(value: T): T { // T泛型
  return value
}
fn<string>('泛型')

// 泛型类
class demo<T>{
  log(value: T): T {
    return value
  }
}
const d = new demo<number>()
console.log(d.log(123));

泛型接口

// 泛型接口(方法1)
interface animal {
  <T>(value: T): T
}
var d: animal = function fn<T>(value: T): T {
  return value
}
console.log(d<string>('123'));

// 泛型接口(方法2)
interface animal<T> {
  (value: T): T
}
var d: animal<string> = function fn(value) {
  return value
}
console.log(d('1234'));

把类作为参数类型的泛型类

// 写法1
class ext {
  name: string | undefined
  sex: string | undefined
}
class demo {
  constructor(str: ext) {
    console.log(str);
  }
}
const d = new demo({ name: 'hfd', sex: '男' })

// 写法2
class ext {
  name: string | undefined
  sex: string | undefined
}
class user<T>{
  add(data: T):boolean {
    console.log('这是data数据', data);
    return true
  }
}
const d = new ext()
d.name = '测试的名字'
d.sex = '女'
const data = new user<ext>()
data.add(d)

模拟数据库操作

// 模拟操作数据库

interface DBL<T> {
  add(info: T): boolean;
  edit(info: T, id: number): boolean;
  delete(id: number): boolean;
  get(id: number): boolean
}
class user {
  name: string | undefined
  age: number | undefined
}
// 定义一个操作mysql数据库的类   注意:实现泛型接口这个类也应该是一个泛型类
class mysql<T> implements DBL<T> {
  constructor() {
    // 在这里可以进行数据库连接等操作
  }
  add(info: T): boolean {
    console.log(info);
    return true
  }
  edit(info: T, id: number): boolean {
    if (info && id) {
      // 提交到数据库
      console.log('修改成功');
    }
    return true
  }
  delete(id: number): boolean {
    if (id) {
      console.log('删除成功');
    }
    return true
  }
  get(id: number): boolean {
    if (id) {
      console.log('查询成功');
    }
    return true
  }
}
const u = new user()
u.name = 'hfd'
u.age = 18
const m = new mysql<user>() // 类作为参数来约束数据传入的类型
m.add(u)
m.edit(u, 123)
m.delete(123)
m.get(123)

命名空间

在代码量较大的情况下,为了避免变量命名冲突,可以将相似功能的函数、类、接口等放到命名空间内

# 命名空间和模块化的区别
命名空间: 内部模块,主要用于组织代码,避免命名冲突
模块: ts外部模块,侧重代码的复用
// 命名空间
interface animal {
  name: string
  games(game: string): void
}
namespace A {
  // 在命名空间内demo为私有类,所以需要导出才可以用
  export class demo implements animal {
    name: string
    constructor(name: string) {
      this.name = name
    }
    games(game: string): void {
      console.log(this.name + "在玩" + game);
    }
  }
}
namespace B {
  // 在命名空间内demo为私有类,所以需要导出才可以用
  export class demo implements animal {
    name: string
    constructor(name: string) {
      this.name = name
    }
    games(game: string): void {
      console.log(this.name + "在玩" + game);
    }
  }
}
// 访问方法
const cat = new A.demo('小猫咪')
cat.games('开心消消乐')
const dog = new B.demo('小狗狗')
cat.games('王者荣耀')

类型推论

image.png

变量`Name`的类型被推断为string,这种推断发生在初始化变量,设置默认参数值时,如果在声明时没有赋值则会被默认推断为any任意类型的值!

高级类型

交叉类型(Intersection Types)

interface IPerson {
  id: string;
  age: number;
}
interface IWorker {
  companyId: string;
}
type IStaff = IPerson & IWorker //主要通过这段代码实现
const staff: IStaff = {
  id: 'E1106',
  age: 5,
  companyId: '蛋仔乐园'
};
 
console.dir(staff)
交叉类型就是将多个类型合并成为一个类型,让这个类型同时拥有所有类型的特性!

联合类型(Union Types)

interface person {
  name: string
  age:number | string
}
联合类型表示一个值可以是几种类型之一, 我们用竖线( `|`)分隔每个类型!如上就age就表示可以是number类型也可以是string类型的数据(只能赋值指定的类型)!

Pick 和 Omit

interface Person {
  name: string;
  age: number;
  id: number;
}
type Woman = Pick<Person, "name" | "id">;
type EditUser = Omit<Person, "id">; 
# Pick
主要是从一个已知的类型中,取出子集,作为一个新的类型返回,上面的代码就表示从Person中取出name和id作为新的类型!
# Omit
Omit与Pick作用相似,只不过Omit是以一个类型为基础支持剔除某些属性,然后返回一个新类型,上面的代码就表示从Person去掉id只留下其他属性,组成一个新的类型!

小结

学到这里TS大概能够完成现在的工作了!更多的可以参考TS官方文档来学习,加油!