TypeScript 常用语法

基础类型

布尔值

// boolean  值 true/false 
let isBoolean:boolean = false;
isBoolean = true;

数字

// number 除了支持十进制和十六进制字面量,还支持 ECMAScript 2015中引入的二进制和八进制字面量。
let a10: number = 10 // 十进制
let a2: number = 0b1010  // 二进制
let a8: number = 0o12 // 八进制
let a16: number = 0xa // 十六进制

字符串

// 可以使用双引号(")或单引号(')表示字符串
let name:string = "crj"
name = 'crj-ts'
const info = `${name}`

undefined 和 null

// undefined 和 null 两者各自有自己的类型分别叫做 undefined 和 null
let und: undefined = undefined
let nul: null = null

数组

// 有两种方式可以定义数组
// 第一种,可以在元素类型后面接上[]
let list:number[] = [1, 2, 3]
// 第二种方式是使用数组泛型,Array<元素类型>
let list:Array<number> = [1, 2, 3]

元组 Tuple

// 元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同
// 元组类型,在定义数组的时候,类型和数据的个数一开始就已经限定
let t1: [string, number]
t1 = ['crj', 10] // OK
t1 = [10, 'crj'] // Error
// 当访问一个已知索引的元素,会得到正确的类型:
console.log(t1[0].substring(1))
console.log(t1[1].toFixed(2)) 

枚举 enum

// enum 类型是对 JavaScript 标准数据类型的一个补充
enum Color {A,B,C}
// 枚举数值默认从0开始依次递增
// 根据特定的名称得到对应的枚举数值
let crj: Color = Color.A // 0
console.log(crj, Color.A, Color.B)

// 默认情况下,从 0 开始为元素编号。 你也可以手动的指定成员的数值。
enum Color {A=1,B,C}
let crj: Color = Color.A // 1

// 枚举类型提供的一个便利是你可以由枚举的值得到它的名字
enum Color {A=1,B,C}
let crj: string = Color[2]
console.log(crj)  // 'B'

any

// 在编程阶段还不清楚类型的变量指定一个类型
let notSure: any = 10
notSure = 'string'
notSure = true// 也可以是个 boolean

let list: any[] = [1, true, 'free']
list[1] = 100
list[2] = 100

void

// void 类型像是与 any 类型相反,它表示没有任何类型。 
// 当一个函数没有返回值时,你通常会见到其返回值类型是 void
/* 表示没有任何类型, 一般用来说明函数的返回值不能是undefined和null之外的值 */
function fn(): void {
  console.log('fn()')
  // return undefined
  // return null
  // return 1 // error
}
// 声明一个 void 类型的变量没有什么大用,因为你只能为它赋予 undefined 和 null
let unusable: void = undefined

object

// 定义一个函数,参数是object类型,返回值也是object类型
function fn2(obj:object):object {
  console.log('fn2()', obj)
  return {}
  // return undefined
  // return null
}
console.log(fn2({name:'crj'))
console.log(fn2(new String('abc')))
// console.log(fn2('abc') // error
console.log(fn2(String))

联合类型

// 联合类型(Union Types)表示取值可以为多种类型中的一种
function toStr(x: number | string) : string {
  return x.toString()
}
console.log(toStr(123))
console.log(toStr('123'))

类型断言

// 类型断言有两种形式。 其一是“尖括号”语法, 另一个为 as 语法
// 定义一个一个函数得到一个数字或字符串值的长度
function getLength(x: number | string) {
  // return x.length // error
  if (x.length) { // error
    return x.length
  } else {
    return x.toString().length
  }
}
function getLength(x: number | string) {
  if ((<string>x).length) {
    return (x as string).length
  } else {
    return x.toString().length
  }
}
console.log(getLength('abcd'), getLength(1234))

类型推断

//  TS会在没有明确的指定类型的时候推测出一个类型
// 1. 定义变量时赋值了, 推断为对应的类型. 
let b9 = 123 // number
// b9 = 'abc' // error

// 2. 定义变量时没有赋值, 推断为any类型
let b10  // any类型
b10 = 123
b10 = 'abc'

接口

接口

TypeScript 的核心原则之一是对值所具有的结构进行类型检查。
在 TypeScript 中,我们使用接口(Interfaces)来定义对象的类型
接口: 是对象的状态(属性)和行为(方法)的抽象(描述)
接口类型的对象 【多了或者少了属性是不允许的】【可选属性: ?】【只读属性: readonly】

/* 
  需求: 创建人的对象, 需要对人的属性进行一定的约束
    id是number类型, 必须有, 只读的
    name是string类型, 必须有
    age 是number类型, 必须有
    sex 是string类型, 可以没有
*/
(()=>{
  // 定义一个接口
  interface InterfacesPerson{
    readonly id:number
    name:string
    age: number
    sex?: string
  }
  // 定义一个对象,该对象的类型就是我定会一的接口 InterfacesPerson
  const ren:InterfacesPerson = {
    id: 1,
    name: 'crj',
    age: 18,
    // sex: '男' // 可以没有
    // xxx: '太丑' // error 没有在接口中定义, 不能有
  }
  console.log("crj", ren)
  // ren.id = 1000 // error 无法分配到 "id" ,因为它是只读属性
  // ren.as = "太丑" // error 类型“InterfacesPerson”上不存在属性“as”
})()

函数类型

函数类型,通过接口的方式作为函数类型使用
为了使用接口表示函数类型,我们需要给接口定义一个调用签名。
它就像是一个只有参数列表和返回值类型的函数定义。
参数列表里的每个参数都需要名字和类型。

(()=>{
  // 定义一个接口,用来作为某个函数的类型使用
  interface InterfacesFun{
    // 定义一个调用签名
    (source: string, subString: string): boolean
  }
  // 定义一个函数,该类型就是上面定义的接口
  const crjString:InterfacesFun = function (source: string, subString: string): boolean{
    return source.search(subString) > -1
  }
  // 调用函数
  console.log(crjString('string,string,string', 'a'))
})()

类类型–类实现接口

类,类型:类的类型可以通过接口来实现

(()=>{
  // 定义一个接口
  interface InterfaceCRJ{
    crj()
  }
  // 定义一个类,这个类的类型就是上面的接口
  class P implements InterfaceCRJ{
    crj(){
      console.log('====================================');
    }
  }
  // 调用函数
  const pp = new P()
  console.log(pp.crj())
})()

一个类可以实现多个接口

(()=>{
  // 定义一个接口
  interface InterfaceCRJ{
    crj()
  }
  // 定义第二个接口
  interface InterfaceCRJOne{
    crjOne()
  }
  // 定义一个类,这个类的类型就是上面的InterfaceCRJ 和 InterfaceCRJOne接口
  // 一个类同时被多个类进行约束
  class P implements InterfaceCRJ,InterfaceCRJOne{
    crj(){
      console.log('====================================');
    }
    crjOne(){
      console.log('====================================One');
    }
  }
  // 调用函数
  const pp = new P()
  pp.crj()
  pp.crjOne()
})()

接口继承接口

// 类,类型:类的类型可以通过接口来实现
(()=>{
  // 定义一个接口
  interface InterfaceCRJ{
    crj()
  }
  // 定义第二个接口
  interface InterfaceCRJOne{
    crjOne()
  }
  // 接口继承接口
  interface InterfaceCRJAndInterfaceCRJOne extends InterfaceCRJ, InterfaceCRJOne {

  }
  
  // 定义一个类,这个类的类型就是上面的InterfaceCRJAndInterfaceCRJOne接口
  class P implements InterfaceCRJAndInterfaceCRJOne{
    crj(){
      console.log('====================================');
    }
    crjOne(){
      console.log('====================================One');
    }
  }
  // 调用函数
  const pp = new P()
  pp.crj()
  pp.crjOne()
})()

基本使用

类:可以理解为模板,通过模板可以实例话对象
面向对象编程思想

(()=>{
  // 类的定义及使用
  class P{
    // 定义属性
    name:string
    age:number
    // 定义构造函数:为了将来实例化对象的时候,可以直接对属性的值进行初始化
    constructor(name:string,age:number = 18){
      // 更新对象中的属性数据
      this.name = name
      this.age = age
    }
    // 定义实例方法
    fun(age:number){
      console.log(`crj${this.name},${this.age},${age}`);
    }
  }
  const a = new P(',crjOne',20)
  a.fun(30)
  
})()

继承

继承:类与类之间的关系
继承后类鱼类之间的叫法:A继承了B这个类,那么此时A类叫子类,B类叫基类
子类–> 又叫派生类
基类–> 又叫超类(父类)

(()=>{
  // 定义一个类(父类,基类,超类)
  class A{
    // 定义属性
    name:string
    age:number
    // 定义构造函数:为了将来实例化对象的时候,可以直接对属性的值进行初始化
    constructor(name:string,age:number = 18){
      // 更新对象中的属性数据
      this.name = name
      this.age = age
    }
    // 定义实例方法
    fun(age:number){
      console.log(`crj${this.name},${this.age},${age}`);
    }
  }

  class B extends A{
    constructor(name:string,age:number){
      // 调用的是父类中的构造函数,使用的是super
      super(name,age)
    }
    // 重写父类型的方法
    fun(){
      console.log("我是B类中的fun方法");
      super.fun(50)
    }
  }
  const a = new A(',crjA',20)
  a.fun(30)

  const b = new B(',crjB',20)
  b.fun()
})()

多态

多态:父类型的引用指向了子类型的对象,不同类型的对象针对相同的方法,产生了不同的行为

(()=>{
  // 定义一个类(父类,基类,超类)
  class A{
    // 定义属性
    name:string
    age:number
    // 定义构造函数:为了将来实例化对象的时候,可以直接对属性的值进行初始化
    constructor(name:string,age:number = 18){
      // 更新对象中的属性数据
      this.name = name
      this.age = age
    }
    // 定义实例方法
    fun(age:number){
      console.log(`crj${this.name},${this.age},${age}`);
    }
  }
  // 定义一个子类
  class B extends A{
    constructor(name:string,age:number){
      // 调用的是父类中的构造函数,使用的是super,实现子类中属性的初始化操作
      super(name,age)
    }
    // 实例方法,重写父类中的实例方法
    fun(){
      console.log("我是B类中的fun方法");
      super.fun(10)
    }
  }
  // 定义第二个子类
  class C extends A{
    constructor(name:string,age:number){
      // 调用的是父类中的构造函数,使用的是super,实现子类中属性的初始化操作
      super(name,age)
    }
    // 实例方法,重写父类中的实例方法
    fun(){
      console.log("我是C类中的fun方法");
      super.fun(20)
    }
  }
  const a:A = new A(',crjA',70)
  a.fun(30)

  const b:B = new B(',crjB',80)
  b.fun()

  const c:C = new C(',crjC',90)
  c.fun()
  // 父类和子类的关系:父子关系,此时,父类类型创建子类的对象
  const d:A = new B(',crjD',100)
  d.fun(60)
  console.log("=======================")
  function showRun(e:A){
    e.fun(120)
  }
  showRun(b)
  showRun(c)
})()

公共,私有与受保护的修饰符

修饰符,类中的成员的修饰符:主要描述类中成员(属性,构造函数,方法)的可访问性
类中的成员都有自己的默认的访问修饰符,public

修饰符名称修饰符描述修饰符理解
public公共默认
private私有当成员被标记成 private 时,它就不能在声明它的类的外部访问
protected受保护protected 修饰符与 private 修饰符的行为很相似,但有一点不同,protected成员在派生类中仍然可以访问
// public修饰符:类中成员默认修饰符,代表是公共的,任何地方都可以访问类中的成员
(()=>{
  class A{
    public name:string
    public constructor(name:string){
      this.name = name
    }
    public fun(age:number){
      console.log(`crj${this.name},${age}`);
    }
  }
  const a:A = new A(',crjA')
  console.log(a.name)
  a.fun(30)
// private修饰符:类中的成员如果使用private修饰,那么外部是无法访问这个成员数据的,当然,子类中也是无法访问
  class B {
    private name:string
    public constructor(name:string){
      this.name = name
    }
    public fun(age:number){
      console.log(`crj${this.name},${age}`);
    }
  }
  class E extends B{
    constructor(name:string){
      super(name)
    }
    fun(){
      console.log('====================================');
      // console.log("继承自B类", this.name); // 这里不可以访问  因为private修饰符
      console.log('====================================');
    }
  }
  
  const b:B = new B(',crjA')
  // console.log(b.name) // 不可访问  因为private修饰符
  b.fun(30)
// protected修饰符:类中的成员使用protected修饰,那么外部是无法访问这个成员数据,当然,子类中是可以访问的
  class C {
    protected name:string
    public constructor(name:string){
      this.name = name
    }
    public fun(age:number){
      console.log(`crj${this.name},${age}`);
    }
  }
  class D extends C{
    constructor(name:string){
      super(name)
    }
    fun(){
      console.log('====================================');
      console.log("继承自C类", this.name); // 这里可以访问  因为protected修饰符
      console.log('====================================');
    }
  }
  
  const c:C = new C(',crjA')
  // console.log(c.name) //c 不可访问  因为protected修饰符
  c.fun(30)
})()

readonly 修饰符 关键字

readonly 修饰类中的成员属性操作

// 对类中的属性成员进行修饰,修饰后,该属性成员就不能在外部随意修改了
(()=>{ 
    class A {
        readonly name:string
        constructor(name:string){
            // 构造函数中,可以对只读属性成员的数据进行修改
            this.name = name
        }
        fun(){
            console.log('crj', this.name);
            // 类中的普通方法中,也是不能修改readonly修饰的成员属性值
            // aa.name = "李" // error 无法分配到 "name" ,因为它是只读属性。
        }
    }
    // 实例化对象
    const aa = new A('张')
    console.log(aa)
    console.log(aa.name);
    // aa.name = "李" // error 无法分配到 "name" ,因为它是只读属性。
    // console.log(aa.name);
})()

(()=>{
    // readonly 修饰类中的构造函数中的参数(参数属性)
    class A {
        constructor(readonly name:string){
        }
    }
    // 实例化对象
    const aa = new A('张')
    console.log(aa.name)
})()

存储器 get set

通过 getters/setters 来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问

class Person {
  firstName: string = 'A'
  lastName: string = 'B'
  get fullName () {
    return this.firstName + '-' + this.lastName
  }
  set fullName (value) {
    const names = value.split('-')
    this.firstName = names[0]
    this.lastName = names[1]
  }
}

const p = new Person()
console.log(p.fullName)

p.firstName = 'C'
p.lastName =  'D'
console.log(p.fullName)

p.fullName = 'E-F'
console.log(p.firstName, p.lastName)

静态成员 static

在类中通过 static 修饰的属性和方法,那么就是静态的属性及静态的方法,也称之为:静态成员
静态成员在使用的时候是通过类名.的这种语法来调用的

(()=>{
    // 定义一个类
    class A {
        name: string = 'A'
        // 静态属性
        static nameA: string = 'nameA'
        constructor(){
            // 此时的this是实例对象,nameA是静态属性,不能通过实力对象直接调用静态属性来使用
            // this.nameA = nameA // error
        }
        // 金泰方法
        static fun(){
            console.log('AA');
        }
    }
    // 实例化对象
    const aa:A = new A()
    // 通过实例对象调用属性
    console.log(aa.name)
    // 通过类.静态属性的方式访问该成员数据
    console.log(A.nameA)
    // 通过类.静态方法的方式访问该成员数据
    A.fun()
})()

抽象类 abstract

抽象类:包含抽象方法(抽象方法一般没有任何的具体内容的实现),也可以包含实例方法,抽象类是不能被实例化,为了让子类实例化及实现内部的抽象方法

(()=>{
    // 定一个抽象类
    abstract class A{
        // 抽象方法,抽象方法 不能有具体的实现
        abstract fun()
        // 实例方法
        run(){
            console.log('都漂亮');
        }
    }
    // 不能实例化抽象类的对象
    // const a:A = new A()

    // 定义一个子类(派生类)B
    class B extends A{
        // 重新实现抽象类中的方法
        fun () {
           console.log('自己实现'); 
        }
    }
    const b:B = new B()
    b.fun()
    // 调用抽象类中的实例方法
    b.run()
})()

函数

基本示例

// 函数: 封装了一些重复使用的代码,在需要的时候直接调用即可
(()=>{
    // js中
    // 函数声明,命名函数
    function add(a,b){
        return a + b
    }
    // 函数表达式,匿名函数
    let addTwo = function (a,b){ 
        return a + b
    }

    // TS中
    // 函数声明,命名函数
    function addTS(a:number,b:number):number{
        return a + b
    }
    // 函数表达式,匿名函数
    let addTwoTS = function (a:number,b:number):number{ 
        return a + b
    }
    // 书写完整函数类型
    let add3TS: (a:number,b:number) => number = function (a:number,b:number):number{ 
        return a + b
    }

	// 可选参数和默认参数
	// 可选参数:函数在声明得时候,内部得参数使用了?进行修饰
	// 默认参数:函数在声明得时候,内部有自己得默认值
	function buildName(firstName: string='A', lastName?: string): string {
	  if (lastName) {
	    return firstName + '-' + lastName
	  } else {
	    return firstName
	  }
	}
	console.log(buildName('C', 'D'))
	console.log(buildName('C'))
	console.log(buildName())
	
	// 剩余参数
	// 剩余参数是放在函数声明的时候所有的参数的最后
	function info(x: string, ...args: string[]) {
	  console.log(x, args)
	}
	info('abc', 'c', 'b', 'a')

	//  函数重载
	// 函数重载: 函数名相同, 而形参不同的多个函数
	// 在JS中, 由于弱类型的特点和形参与实参可以不匹配, 是没有函数重载这一说的 但在TS中, 与其它面向对象的语言(如Java)就存在此语法
	// 重载函数声明
	function add (x: string, y: string): string
	function add (x: number, y: number): number
	
	// 定义函数实现
	function add(x: string | number, y: string | number): string | number {
	  // 在实现上我们要注意严格判断两个参数的类型是否相等,而不能简单的写一个 x + y
	  if (typeof x === 'string' && typeof y === 'string') {
	    return x + y
	  } else if (typeof x === 'number' && typeof y === 'number') {
	    return x + y
	  }
	}
	
	console.log(add(1, 2))
	console.log(add('a', 'b'))
	// console.log(add(1, 'a')) // error
})()

泛型

指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。

// 下面创建一个函数, 实现功能: 根据指定的数量 count 和数据 value , 创建一个包含 count 个 value 的数组 
// 不用泛型的话,这个函数可能是下面这样:
function createArray(value: any, count: number): any[] {
  const arr: any[] = []
  for (let index = 0; index < count; index++) {
    arr.push(value)
  }
  return arr
}

const arr1 = createArray(11, 3)
const arr2 = createArray('aa', 3)
console.log(arr1[0].toFixed(), arr2[0].split(''))

// 使用函数泛型
function createArray2 <T> (value: T, count: number) {
  const arr: Array<T> = []
  for (let index = 0; index < count; index++) {
    arr.push(value)
  }
  return arr
}
const arr3 = createArray2<number>(11, 3)
console.log(arr3[0].toFixed())
// console.log(arr3[0].split('')) // error
const arr4 = createArray2<string>('aa', 3)
console.log(arr4[0].split(''))
// console.log(arr4[0].toFixed()) // error

多个泛型参数的函数

function swap <K, V> (a: K, b: V): [K, V] {
  return [a, b]
}
const result = swap<string, number>('abc', 123)
console.log(result[0].length, result[1].toFixed())

泛型接口

在定义接口时, 为接口中的属性或方法定义泛型类型
在使用接口时, 再指定具体的泛型类型

interface IbaseCRUD <T> {
  data: T[]
  add: (t: T) => void
  getById: (id: number) => T
}
class User {
  id?: number; //id主键自增
  name: string; //姓名
  age: number; //年龄
  constructor (name, age) {
    this.name = name
    this.age = age
  }
}
class UserCRUD implements IbaseCRUD <User> {
  data: User[] = []
  add(user: User): void {
    user = {...user, id: Date.now()}
    this.data.push(user)
    console.log('保存user', user.id)
  }
  getById(id: number): User {
    return this.data.find(item => item.id===id)
  }
}
const userCRUD = new UserCRUD()
userCRUD.add(new User('tom', 12))
userCRUD.add(new User('tom2', 13))
console.log(userCRUD.data)

泛型类

在定义类时, 为类中的属性或方法定义泛型类型 在创建类的实例时, 再指定特定的泛型类型

class GenericNumber<T> {
  zeroValue: T
  add: (x: T, y: T) => T
}

let myGenericNumber = new GenericNumber<number>()
myGenericNumber.zeroValue = 0
myGenericNumber.add = function(x, y) {
  return x + y 
}

let myGenericString = new GenericNumber<string>()
myGenericString.zeroValue = 'abc'
myGenericString.add = function(x, y) { 
  return x + y
}
console.log(myGenericString.add(myGenericString.zeroValue, 'test'))
console.log(myGenericNumber.add(myGenericNumber.zeroValue, 12))

泛型约束

// 如果我们直接对一个泛型参数取 length 属性, 会报错, 因为这个泛型根本就不知道它有这个属性
// 没有泛型约束
function fn <T>(x: T): void {
  // console.log(x.length)  // error
}
// 我们可以使用泛型约束来实现
interface Lengthwise {
  length: number;
}
// 指定泛型约束
function fn2 <T extends Lengthwise>(x: T): void {
  console.log(x.length)
}
// 我们需要传入符合约束类型的值,必须包含必须 length 属性:
fn2('abc')
// fn2(123) // error  number没有length属性

内置对象

ECMAScript 的内置对象

/* 1. ECMAScript 的内置对象 */
let b: Boolean = new Boolean(1)
let n: Number = new Number(true)
let s: String = new String('abc')
let d: Date = new Date()
let r: RegExp = /^1/
let e: Error = new Error('error message')
b = true
// let bb: boolean = new Boolean(2)  // error

BOM 和 DOM 的内置对象

Window
Document
HTMLElement
DocumentFragment
Event
NodeList

const div: HTMLElement = document.getElementById('test')
const divs: NodeList = document.querySelectorAll('div')
document.addEventListener('click', (event: MouseEvent) => {
  console.dir(event.target)
})
const fragment: DocumentFragment = document.createDocumentFragment()
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端全栈分享站

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值