ts基础语法 二

113 阅读4分钟

class 类

构造函数:

需要为构造函数指定类型注解,否则会被隐式推断为 any ;构造函数不需要返回值类型

class Person {
    name:string
    age:number
    constructor(name:string,age:number){
        this.name = name
        this.age = age
    }
}
let p = new Person('lf',18)
console.log(p);

类继承的两种方式:

  1. extends (继承父类)
class Animal {
  eat() {
    console.log("吃狗粮");
  }
}
class Dog extends Animal {
  name = "旺财";
  sing() {
    console.log("汪汪");
  }
}
let dog = new Dog();
console.log(dog.eat());
console.log(dog.name);

2 implements 关键字 (实现接口)

Person 类中必须提供 Skills 接口中指定的所有方法和属性

interface Skills {
    Sing():void 
    Play():void
}
class Person implements Skills {
    Sing(){
        console.log('爱你一万年');
    }
    Play(){
        console.log('吃鸡');
    }
}

类成员可见性

  • public: 表示公有的、公开的,公有成员可以被任何地方访问,默认可见性
  • protected: 表示受保护的,仅对其声明所在类和子类中(非实例对象)可见
  • private: 表示私有的,只在当前类中可见,对实例对象以及子类也是不可见的
// public 公开的
// protected 受保护的
// private 私有的
class Animal {
   protected eat() {
      console.log("吃狗粮");
    }
    private drink(){
        console.log('喝可乐');
    }
    play(){
        this.eat() // 可以调用eat 方法
        this.drink() // 可以调用drink 方法
        console.log('跳一跳');
    }
  }
  let animal = new Animal()
  // 不能调用Animal类中的eat 方法 
  // 不能调用Animal类中的drink 方法
  animal.play()  
​
  class Dog extends Animal {
    name = "旺财";
    sing() {
      this.eat()  // 可以调用Animal类中的eat 方法
      //this.drink()  不能调用Animal类中的drink 方法 (私有的)
      console.log("汪汪");
    }
  }
  let dog = new Dog();
  // 不能调用Animal类中的eat 方法
  // 不能调用Animal类中的drink 方法
  dog.name  
  dog.play()
  dog.sing()

readonly(只读修饰符)

readonly: 表示只读,用来防止在构造函数之外对属性进行赋值

使用 readonly 关键字修饰该属性是只读的,注意只能修饰属性不能修饰方法

接口或者 {} 表示的对象类型,也可以使用 readonly

class Person1 {
    name:string
    readonly age:number = 18 //默认18
    constructor(a:string,b:number){
        this.name = a
        this.age = b
    }
}
let p = new Person1('lf',20)
p.name = '路飞'
//p.age = 20  //只读,不能修改//接口写法
interface Person2 {
   readonly name:string
}
let obj:Person2 = {
    name:'路飞'
}
//obj.name = '娜美'  //只读,不能修改let obj1:{readonly name:string} = {
     name:'路飞'
 }
 //obj1.name = '娜美'  //只读,不能修改

类型兼容性

  1. Structural Type System(结构化类型系统)

    TS 采用的是结构化类型系统,也叫做 duck typing(鸭子类型),类型检查关注的是值所具有的形状

  2. Nominal Type System(标明类型系统)

    (比如,C#、Java等)

interface Named {
    name: string;
}
class Person {
    name: string;
}
let p: Named;
​
p = new Person();   //ts可以兼容   C#、Java 等不能兼容
  • 接口兼容性:

    成员多的 可以赋值给成员少的

interface X {
  a: number;
  b: number
}
​
interface Y {
  a: number;
  b: number;
  c: number
}
let x: X = { a: 1, b: 2 }
let y: Y = { a: 1, b: 2, c: 3 }
​
x = y // YES
y = x // ERROR 类型 "X" 中缺少属性 "c",但类型 "Y" 中需要该属性。
​
  • 函数的兼容性

    比较参数: 参数可以少但是不能多

let x = (a: number) => 0;
let y = (b: number, s: string) => 0;y = x; // YES
x = y; // Error 不能将类型“(b: number, s: string) => number”分配给类型“(a: number) => number”。
比较返回值:  返回值类型必须是目标函数返回值类型的子类型。(**少了不行,多了可以**)
let x = () => ({name: 'Alice'});
let y = () => ({name: 'Alice', location: 'Seattle'});x = y; // YES
y = x; // Error, 不能将类型“() => { name: string; }”分配给类型“() => { name: string; location: string; }”。
// 类型 "{ name: string; }" 中缺少属性 "location",但类型 "{ name: string; location: string; }" 中需要该属性。

交叉类型

  • 交叉类型&:功能类似于接口继承extends,用于组合多个类型为一个类型(常用于对象类型)
interface P1 {name:string}
interface P2 {age:number}
type P3 = P1 & P2   //P3同时拥有了P1和P2所有属性类型
let person:P3 = {
   name:'路飞',
   age:18 
}   
  • 交叉类型& 和接口继承extends 的对比: l 相同点:都可以实现对象类型的组合。 l 不同点:两种方式实现类型组合时,对于同名属性之间,处理类型冲突的方式不同。

泛型

泛型 : 在定义函数,接口,类的时候不能预先确定数据类型,而是在使用函数,接口,类的时候才能确定数据类型

  function getArr<T>(value:T,count:number) : T[] {
    const arr:Array<T> = [];
    for(let i = 0;i<count;i++){
      arr.push(value)
    };
    return arr;
  }
const arr1 =  getArr<string>('timi',5)
const arr2 =  getArr<number>(100.2222,5)
console.log(arr1[0].split(','));  // arr1[0] 有智能提示
console.log(arr2[0].toFixed(2)); // arr2[0] 有智能提示
 //多个泛型函数参数
  function getArr<K, V>(value1: K, value2: V): [K, V] {
    return [value1, value2];
  }
  const arr1 = getArr<string,number>("tim", 22.222)
  console.log(arr1[0].split(''));
  console.log(arr1[1].toFixed(1));