01- TypeScript高级类型

136 阅读3分钟

TypeScript高级类型

1. class的基本使用

js提供了class类。TS在此之上 还提供了相应的修饰符 比如:get set

TS中的class,不仅提供了class的语法功能,也作为一种类型存在

class Person {
  // 直接定义
  age: number
  // 有默认值
  gender = '男'
}

const p = new Person()

p.age
p.gender

2. 构造函数

class Person {
  age:number;
  gender:string;
  
  constructor(age:number,gender:string) {
    this.age = age
    this.gender = gender
  }
}

const p = new Person(30,'女')

console.log(p.age,p.gender)

3. 实例方法

class Point {
  x = 1
  y = 2
  
  scale(n:number):void {
    this.x *= n
    this.y *= n
  }
}

const p = new Point()

p.scale(10)
console.log(p.x,p.y)

4. 继承 extends

class Animal {
  move() {
    console.log('走两步')
  }
}

class Dog extends Animal {
  name = '二哈'
  
  bark() {
    console.log('旺旺!')
  }
}
const d =new Dog()
d.move()
d.bark()

5. 接口

  • 通过implements关键字 让class 实现接口。
interface Singable {
  sing(): void
}

class Person implements Singable{
  sing() {
    console.log('hello world')
  }
}

6. 类的修饰符

1. public

表示公开的,可以被任何地方访问

class Person {
  public move() {
    console.log('走两步')
  }
}

const p = new Person()
p.move()

2. protected

表示受保护的,仅在声明所在类和子类(非实例)可见

class Person {
  protected move() {
    console.log('走两步')
  }
}

class Man extends  Person {
  run () {
    this.move()
  }
}

const p = new Person()
p.move() // 不能访问

3. private

Private: 表示私有的,只在当前类中可见

class Person {
  private __move__() {
    console.log('走两步')
  }
}

class Man extends  Person {
  run () {
    this.__move__() //不能访问
  }
}

const p = new Person()
p.__move__() // 不能访问

7. readonly修饰符

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

class Person {
  readonly age:number = 18
  // 只能在constructor中赋值
  constructor(age:number) {
    this.age = age
  }
}

8. 类型兼容性

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

TS采用的是结构化类型系统

  • 在结构化类型系统中,如果两个对象具有相同的形状,认为这是同一个类型
class Point {x:number;y:number}
class Point2D {x:number;y:number}

const p:Point = new Point2D()

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

C# java 用的是这种

class Point {x:number;y:number}
class Point2D {x:number;y:number}

const p:Point = new Point2D()
// 会报错

9. 交叉类型

类似于接口继承(extends),用于组合多个类型为一个类型(常用于对象类型)

interface Person {name:string}

type PersonDetail = {phone:string}  & Person

交叉类型和接口继承对比

  • 相同点:都可以实现对象类型的组合。
  • 不同点:俩种方式实现类型组合式,对于同名属性直接,处理类型冲突的方式不同
interface A {
  fn:(value:number) => string
}
interface B extends A{
  fn:(value:string) => string // 会报错
}

//////////////////////   分割线   /////////////////////////

interface A {
  fn:(value:number) => string
}
interface B {
  fn:(value:string) => string
}
type Contact = A & B
好比 fn:(value:string | number) => string


说明:以上代码,接口继承会报错;交叉类型没有错

10. 泛型

相当于插槽 占位符

// 创建
function id<T>(value:T):T{
  return value
}

// 使用
id<number>()

类型约束

// 创建
function id<T extends arrary>(value:T):T{
  value.length
  return value
}

多个泛型变量的情况

泛型可以有多个 类型变量之间还可以约束

// 创建
function getProp<T,K extends keyof T>(obj:T,key:K){
  return obj[key]
}
// 使用
let person = {name:'jack',age:18}
getProp(person,'name')

getProp(['a'],'length')

泛型接口

// 创建
interface IdFunc<T> {
  id:(value:T) => Type
  ids:() => Type[]
}
// 使用
let obj:IdFunc<number> = {
  id(value) {return value},
  ids() {return [1]}
}

泛型类

class 也可以配合泛型

// react中使用
interface IState {count: number}
interface IProps {maxLength: number}

class InputCount extends React.Component<IProps,IState> {
  state = {
    count: 0
  }
  render() {
    return <div>{this.props.maxLength}</div>
  }
}


// 创建
class GenericNumber<T>{
  defaultValue:T
  add: (x:T) => T
}

// 使用
const myNumber = new GenericNumber<number>()
myNumber.defaultValue

索引签名类型

使用场景:当无法确定对象中有哪些属性

interface AnyObject {
  [key:string]:number
}

映射类型

  • 映射类型基于索引签名类型的
  • key in PropKeys 表示key可以是联合类型中的任意一个 类似于 for in(let k in obj)
  • 注意:映射类型只能在类型别名中使用,不能在接口中使用
type PropKeys = 'x' | 'y' | 'z'
type TypeObject = {[key in PropKeys]:number}

// in keyof 配合
type Props = {a:number; b:string; c:string}
type Props3 = {[key in keyof Props]: number}

// keyof Props 获取到对象类型所有key变成联合类型 'a' | 'b' | 'c'
// in 遍历了所有 key

索引查询类型

type Props = {a:string,b:string,c:boolean}
type TypeA = Props['a'|'c']

type TypeB = Props[keyof Props]