【TypeScript】001-类型、接口、函数、类

原始类型:Number,String,Boolean,null,undefined,Symbol 引用类型:Array,Function,Object TypeScript在ES6的数据类型基础上,新增了如下数据类型:void, any, never, 元组,枚举,高级类型web

1、类型

1.1 Number类型

let cml: number = 1
// es5: let cml = 1
复制代码

1.2 String类型

let cml: string = '1'
// es5: let cml = '1'
复制代码

1.3 Boolean类型

let cml: boolean = true
// es5: let cml = true
复制代码

1.4 Null类型

let cml:null = null
// es5: let cml = null
复制代码

1.5 Undefined类型

let cml:undefined = undefined
// es5: let cml = undefined
复制代码

1.6 Symbol类型

const s2: symbol = Symbol(); // TypeScript
const s1 = Symbol();  // es5
console.log(s1 === s2) // false
复制代码

1.7 Void类型

void类型能够被赋值为undefined和null,可是不能被赋值其余的,好比stringtypescript

let cml:void = undefined
// es5: let cml = undefined
cml = null
复制代码

小结:TypeScript会作静态类型检查,当一个变量被定义了某种类型后,再赋值为其余类型的值时,则会有报错提示 image.png数组

可是markdown

  1. 当被从新赋值为null和undefined时,则不会报错,由于null和undefined能够当作是全部类型的子集

image.png 2. 被定义为null和undefined类型的,只能赋值为它自己函数

1.8 对象

// let cml: Object = {x: 1, y: 1} // 不能直接写Object,须要具体定义包含的属性以及对应的类型
let cml: {x: number, y: number} = {x: 1, y: 1}
cml.x = 2
console.log(cml)
复制代码

1.9 数组

1 类型+方括号ui

let cml: number[] = [1, 2, 3]
// es5: let web = [1, 2, 3]
let web: any[] = [1, '2', true]

复制代码

2 泛型this

let cml: Array<number> = [1, 2, 3]
// es5: let cml = [1, 2, 3]
复制代码

3 接口es5

类数组: 内置对象:IArgumenTypeScript, NodeList, HTMLCollectionspa

function web(name: string, age: number) {
  let args: IArgumenTypeScript = argumenTypeScript;
  console.log(args);  // { '0': 'web', '1': 1 }
}
web('web', 1)
复制代码

1.10 元组

元组是一种特殊的数组,限定了数组的类型和个数翻译

let cml: [string, number] = ['666', 666]
console.log(cml) // [ '666', 666 ]
复制代码

使用下标的方式,能够只对其中一项赋值,可是对整个对象赋值时,必须是完整的,且类型不能错,个数不能多也不能少

let cml: [string, number] = ['666', 666]
cml[0] = '888'
console.log(cml) // ['888', 666]
cml[1] = 888
console.log(cml) // ['888', 888]
cml = ['888', 888]
console.log(cml) // ['888', 888]
cml = ['888', 888, '888'] // 报错
复制代码

元组的越界:能够经过push的方式放入更多的元素,能够push,可是仍然不能访问

let cml: [string, number] = ['666', 666]
cml.push('888')
console.log(cml) // ['666', 666, '888']
console.log(cml[2]) // 报错
复制代码

1.11 any类型

any类型能够任意赋值,不写至关于any

let cml:any = '123'
cml = 123
复制代码

1.12 never类型

never 类型表示的是那些永不存在的值的类型。例如,never 类型是那些老是会抛出异常或根本就不会有返回值的函数表达式。

// 抛出异常的函数
let error: never = () => {
  throw new Error('error')
}

// 死循环函数
let endLess: never = () => {
  while(true) {}
}
复制代码

1.13 联合类型

let cml:string | number
cml = '123'
cml = 123
复制代码

类型断言 是针对联合类型,能够经过断言为变量指定一个类型

function cml(a: number | string): void {
  console.log(a.length) // 报错
  console.log((<string>a).length) // OK
}
复制代码

类型别名 除了规定的string/number等类型,TypeScript还支持自定义类型

type Cml = '666' | '888'
function cmlFun(a: Cml): void {
  console.log(a)
}
cmlFun('666') // OK
cmlFun(666) // 报错
复制代码

1.14 enum枚举类型

1. 基本用法

enum Gender {Male, Female}
console.log(Gender) // {'0': 'Male', '1': 'Female', 'Male': 0, 'Female', 1}
console.log(Gender['0']) // Male
console.log(Gender['1']) // FeMale
console.log(Gender['Male']) // 0
console.log(Gender['Female']) // 1
复制代码

对应的ES5的写法

// typescript
enum Gender {Male, Female}

// ES5
var Gender;
(function (Gender) {
    Gender[Gender["Male"] = 0] = "Male";
    Gender[Gender["Female"] = 1] = "Female";
})(Gender || (Gender = {}));
复制代码

2. 数字的枚举

enum Direction {
  NORTH, // 默认0
  SOUTH, // 默认1
  EAST, // 默认2
  WEST, // 默认3
}
let dir: Direction = Direction.EAST;
console.log('dir', dir) // 2
复制代码

默认为0,1,2,3...,若是自定义数字,则后面的枚举在前一个枚举值上加1

enum Direction1 {
  NORTH = -1,
  SOUTH, // 变成0
  EAST = 4,
  WEST, // 变成5
}
复制代码

注意,自加的枚举数值,不保证和已经设定的数值不重合

enum Direction1 {
  NORTH = 1,
  SOUTH = 0,
  EAST,
  WEST,
}
console.log(Direction1)
复制代码

image.png

也能够把数字变成小数

enum Direction1 {
  NORTH = 1.5,
  SOUTH, // 2.5
  EAST, // 3.5
  WEST, // 4.5
}
console.log(Direction1)
复制代码

3. 字符串的枚举

enum Direction1 {
  NORTH = 'a',
  SOUTH = 'b', 
  EAST = 'c', 
  WEST = 'd', 
}
console.log(Direction1)  // { NORTH: 'a', SOUTH: 'b', EAST: 'c', WEST: 'd' }
console.log(Direction1['NORTH']) // a
console.log(Direction1['a'])  // undefined
复制代码

4. 常量枚举

常量枚举是它是使用const关键字修饰的枚举,普通枚举有对象,常量枚举没有对象,对象实体只存在于TypeScript中,当翻译为ES5代码时,被删除了。

用途:当咱们不须要这个对象,只须要对象里的值时,适用常量枚举,能够减小编译时的代码

// TypeScript 代码
const enum Gender {Male, Female}
let cml: Gender = Gender['Female']
console.log(cml)  // 1

// ES5 代码
var cml = 1 /* 'Female' */;
console.log(cml);
复制代码

5. 异构枚举

异构枚举的成员值是数字和字符串的混合:

enum Cml {
  A,
  B,
  C = "c",
  D = "d",
  E = 8,
  F,
}
复制代码

数字枚举和字符串枚举不一样的是,数字枚举相对字符串枚举多了 “反向映射”:

console.log(Cml[0]) // A
console.log(Cml['A']) // 0
console.log(Cml['C']) // c
console.log(Cml['c']) // undefined
复制代码

2、接口

1. 肯定属性

// 定义一个接口
interface IPerson {
  name: string,
  age: number
}

// 实例化
let p1: IPerson = {
  name: 'web',
  age: 18
}
复制代码

一个变量,如上面的p1,若是被声明为某一种接口的实例,则变量拥有的属性必需要和接口定义的同样,不能多也不能少,不然会报错。

2. 可选属性

interface IPerson {
  name: string,
  age?: number
}

// 实例化
let p1: IPerson = {
  name: 'web',
}
复制代码

3. 任意属性

interface IPerson {
  name: string,
  [propName: string]: boolean | string
}

let p1: IPerson = {
  name: '123',
  married: false, // ok
  country: '123' // ok
  age: 123 // 报错
}
复制代码

若是设定了任意属性,那么全部的肯定属性或者可选属性必须是任意属性的子集。

4. 只读属性

interface IPerson {
  readonly name: string,
  age: number
}

let p1: IPerson = {
  name: '123',
  age: 18
}

let p2: IPerson = {
  name: '456', // ok
  age: 18
}

p1.name = '456' // 报错
p1.age = 18
复制代码

readonly,指的是若是不在每次对象赋值状况下,是不能修改值的。

3、函数

1. 函数定义

TypeScript有四种方式去定义函数:

  1. 函数的声明
  2. 函数的表达式
  3. 函数的别名
  4. 接口定义函数

函数的声明

// ES5里函数的声明
function cml(x, y) {
  return x + y
}
console.log(cml(1, 2))  // 3

// TypeScript里函数的声明
function cml(x: number, y: number): number {
  return x + y
}
console.log(cml(1, 2))  // 3
复制代码

函数的表达式

// ES5函数的表达式
let cml = function(x, y) {
  return x + y
}
console.log(cml(1, 2))  // 3

// TypeScript里函数的表达式
let cml = function(x: number, y: number): number {
  return x + y
}
console.log(cml(1, 2))  // 3
复制代码

函数的别名

type cmlFun = (x: number, y: number) => x + y
let cml: Cml = (a, b) => a + b
console.log(cml(1, 2))  // 3
复制代码

接口形式定义函数

interface ICml {
  (x: number, y: number): number
}

let cml: ICml = function(x: number, y: number) : number {
  return x + y
}
console.log(cml(1, 2))  // 3
复制代码

2.可选参数

一个可选参数后面不能再有肯定(必须)参数

function cml(x: number, y?: number): number {
  y = y || 0
  return x + y
}
console.log(cml(1, 2))  // 3
console.log(cml(1))  // 1
复制代码

3.剩余参数

回忆一下ES5里的argumenTypeScript和ES6里的args ES5的argumentTypeScript

function cml() {
  let sum = 0
  for(let item of arguments) {
    sum = sum + item
  }
  return sum
}
console.log(cml(1, 2, 3)) // 6
复制代码

ES6的args

function cml(...args) {
  let sum = 0
  for(let item of args) {
    sum = sum + item
  }
  return sum
}
console.log(cml(1, 2, 3)) // 6
复制代码

TypeScript里的剩余参数

function cml(...args: number[]) {
  let sum: number = 0
  for(let i: number = 0; i < args.length; i ++) {
    sum = sum + args[i]
  }
  return sum
}
console.log(cml(1, 2, 3)) // 6
console.log(cml(1, '2', 3)) // 报错
复制代码

4. 函数重载

C++里的函数重载:函数能够重名,可是参数个数需不一样,或者参数个数相同可是参数类型不一样,编译器经过参数的个数和类型来判断究竟是调用了哪一个参数。

TypeScript的函数重载,仍是只有一个函数,可是能够对不一样的参数组合进行静态类型检查

function cmlFun(arr: number[]) function cmlFun(arr: string[]) function cmlFun(arr: any[]) { if (typeof(arr[0]) === 'number') { return arr.reduce((pre, cur) => pre + cur) } else if (typeof(arr[0]) === 'string') {
    return arr.reduce((pre, cur) => pre + cur)
  }
}
console.log(cmlFun([1, 2, 3])) // 6
console.log(cmlFun(['1', '2', '3'])) // 123
复制代码

4、类

ES6里的类和继承

// 父类
class Father {
  constructor (name, age) {
    this.name = name
    this.age = age
  }
}

// 子类
class Son extends Father{
    constructor(phone, ...args) {
        super(...args)
        this.phone = phone
    }
    f() {
        console.log('this.name', this.name)
    }
}

let s = new Son('17807727381', '父类', '36')
s.f() // this.name 父类
复制代码

1. static关键字(ES6+)

static静态属性和静态方法不能经过new的方式调用。

class Father {
    static phone = '17723812637'
    static f() {
        console.log('this.phone', this.phone)
    }
    constructor (name, age) {
      this.name = name
      this.age = age
    }
}
  
let fa = new Father('17807727381', '父类', '38')
fa.f() // 报错

Father.f()  // this.phone 17723812637
复制代码

2. public关键字

用于修饰类的属性以及方法,用public修饰的属性和方法在类内、外均可以调用。

class Father {
  // 须要先定义
  public name: string
  public age: number
  public constructor (name, age) {
    this.name = name
    this.age = age
  }
  public f() {
    console.log(this.name, this.age)
  }
}

let fa = new Father('父类', 36) // 有构造函数,参数不能省略
fa.f() // 父类 36
复制代码

3. protected关键字

用于修饰类的属性以及方法,用protected修饰的属性和方法,只能由类或者子类的函数访问。

// 父类
class Father {
  protected name: string
  public age: number
  public constructor (name, age) {
    this.name = name
    this.age = age
  }
  f1() {
    console.log('this.name', this.name)
  }
}

// 子类
class Son extends Father{
    public phone: string
    constructor(phone, ...args: [string, number]) {
        super(...args)
        this.phone = phone
    }
    f2() {
        console.log('this.name', this.name)
    }
}
let fa = new Father('父类', 36)
fa.f1() // this.name 父类 (父类经过函数访问: OK)

let s = new Son('17807727381', '父类', 36)
s.f2() // this.name 父类 (子类经过函数访问: OK)

let fa = new Father('父类', 36)
console.log(fa.name) // 报错
console.log(fa.age) // 36
复制代码

4. private关键字

用于修饰类的属性以及方法,用protected修饰的属性和方法,只能由类函数访问

// 父类
class Father {
  private name: string
  public age: number
  public constructor (name, age) {
    this.name = name
    this.age = age
  }
  f1() {
    console.log('this.name', this.name)
  }
}

// 子类
class Son extends Father{
    public phone: string
    constructor(phone, ...args: [string, number]) {
        super(...args)
        this.phone = phone
    }
    f2() {

        console.log('this.name', this.name)  // 报错
    }
}
let fa = new Father('父类', 36)
fa.f1() // this.name 父类 (父类经过函数访问: OK)

let s = new Son('17807727381', '父类', 36)
s.f2() // 报错 (子类经过函数访问: 不OK)

let fa = new Father('父类', 36)
console.log(fa.name) // 报错
console.log(fa.age) // 36
复制代码

5. abstract关键字

抽象类:不可实例化,不能直接new出实例来

abstract class Father {
  // 须要先定义
  public name: string
  public age: number
  public constructor (name, age) {
    this.name = name
    this.age = age
  }
  public f() {
    console.log(this.name, this.age)
  }
}

let fa = new Father('父类', 36) // 报错
fa.f() 
复制代码

抽象方法的使用, 若是子类继承的父类里有抽象方法,则需在子类里实现父类的抽象抽象方法

abstract class Father {
  // 须要先定义
  public name: string
  public age: number
  public constructor (name, age) {
    this.name = name
    this.age = age
  }
  public abstract f1(): void
}

class Son extends Father{
  public phone: string
  constructor(phone, ...args: [string, number]) {
    super(...args)
    this.phone = phone
  }
  public f2(): void {
    console.log('this.name', this.name)
  }

  public f1(): void {
    console.log('this.name', this.name)
  }
}

let fa: Father = new Son('17836762323', '父类', 36)
fa.f1() // this.name 父类

复制代码
相关文章
相关标签/搜索