typescript高级类型笔记

交叉类型

// 交叉类型  交叉类型用&来定义,交叉类型相当于合并T对象和U对象,返回的对象要既包含T的属性也包含U的属性
const mergeFunc = <T, U>(arg1: T, arg2: U): T & U => {
  let res = {} as T & U
  res = Object.assign(arg1, arg2)
  return res
}
console.log(mergeFunc({ a: '1' }, { b: '2' }))  //{a: '1',b: '2'}

联合类型

//联合类型  联合类型用|来定义,联合类型相当于使用T对象或U对象
const getLengthFunc = (content: string | number): number => {  // content的类型只能是string或number
  if (typeof content === 'string') return content.length
  else return content.toString().length
}

类型保护

//类型保护 类型保护的作用 确定使用联合类型时使用的具体是哪个类型
const valueList = ['abc', 123]
const getRandomValue = () => {  //返回的是string和number的联合类型,并且无法确定函数返回的类型是string还是number
  const number = Math.random() * 10
  if (number > 5) { return valueList[0] }
  else return valueList[1]
}
const res = getRandomValue()
//普通方法
if ((res as string).length) {  // 由于无法确定返回的是联合类型中的哪一种所以在调用方法之前要使用类型断言
  console.log((res as string).length)  
} else {
  console.log((res as number).toFixed())
}
//类型保护方法一  自定义类型保护返回值是一个类型谓词,谓词为 parameterName is Type这种形式, parameterName必须是来自于当前函数签名里的一个参数名。
function isString(value:number | string): value is string {
  return typeof value === 'string'
}
if (isString(res)) {
  res.length  // 上面是string类型,else后只有number类型
} else {
  res.toFixed
}
//类型保护方法二  typeof类型保护使用两个条件 1、只能使用===或!==来比较  2、只能比较string\number\boolean\symbol中的一种
if (typeof res === 'string') {
  console.log(res.length)
} else {
  console.log(res.toFixed)
}
//类型保护方法三  instanceof类型保护
class Class1 {
  public age = 11
  constructor() {}
}
class Class2 {
  public name = 'abc'
  constructor() {}
}
function getRandomItem() {
  return Math.random() < 0.5 ? new Class1(): new Class2()
}
let result = getRandomItem()
if (result instanceof Class1) {
  result.age
} else {
  result.name
}

null和undefined

//null和undefined
//默认情况下定义的所有数据类型都是type | undefined | null的联合类型
let a: string = undefined // 所以可以设置值为undefined
let b: string = null
//类型断言
function getSplicedStr(num: number | null): string {
  function getRes(prefix: string) {
    return prefix + num!.toFixed().toString()   // 使用后跟!来断言不为null
  }
  num = num || 0.1
  return getRes('xiecong-')
}

类型别名

//类型别名  相当于给类型起了一个新的名字,可以用新的名字取定义变量,类型别名不会新建一个类型,它创建了一个新名字来引用那个类型
type TypeString = string
let strTest1: string = '111'
let strTest2: TypeString = '222'
type PositionType<T> = { x: T, y: T }
const position1: PositionType<number> = {
  x: 1,
  y: 2
}

/* 可辨识联合要具有3个要素
1、要具有普通的单例类型属性 --- 可辨识的特征
2、一个类型别名包含了类型的联合 
3、此属性上的类型保护
*/
interface Square{
  kind: 'square'
  size: number
}
interface Rectangle {
  kind: 'rectangle'
  width: number
  height: number
}
interface Circle {
  kind: 'circle'
  radius: number
}
type Shape = Square | Rectangle | Circle  //将三个接口做联合类型并起一个别名Shape
function area(s: Shape) {
  // 使用三个类型中共有的可辨识特征kind属性做判断
  switch (s.kind) {
      case "square": return s.size * s.size;
      case "rectangle": return s.height * s.width;
      case "circle": return Math.PI * s.radius ** 2;
  }
}

this类型

// this类型
class Counters {
  constructor(public count: number = 0) { }
  public add(value: number) {
    this.count += value
    return this   // 通过返回this的形式实现了链式调用
  }
  public substract(value: number) {
    this.count -= value
    return this
  }
}
let counter1 = new Counters(10)
counter1.add(3).substract(2) // 通过返回this的形式实现了链式调用

keyof

// keyof
interface InfoInterfaceAdvanced {
  name: string;
  age: number
}
let infoProp: keyof InfoInterfaceAdvanced  // 使用keyof将InfoInterfaceAdvanced的属性名作为字符串字面量类型的联合类型
infoProp = 'name'
infoProp = 'age'  // 值只能有name和age两种
// keyof案例二
function getValue<T, K extends keyof T>(obj: T, names: K[]) {
  return names.map(n => obj[n])
}
const infoObj = {
  name: 'lison',
  age: 18
}
let infoValues:Array<string | number> = getValue(infoObj,['name'])

interface Objs<T> {
  [key:string]: T
}
const objs1: Objs<number> = {
  age: 18
}

映射类型

// 映射类型(映射类型是给一个接口的所有属性加上特征,如readonly、?可选等)
interface Info {
  name: string
  age: number
  higer: number
}
type ReadonlyType<T> = {
  readonly [P in keyof T]?: T[P]  // 给传入的所有属性上加上readonly和?
}
type ReadonlyInfo = ReadonlyType<Info>
let info2: ReadonlyInfo = {
  name: '111',
  age: 2
}
// ts中内置的几个映射类型(Readonly给所有属性加只读、Partial给所有属性加可选、Pick取对象中部分属性重新组成对象、Record)
//Pick原理
let objPick = {
  name: 'xiexiaochongchong',
  age: 18,
  address: 'tiantang'
}
function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
  const res: any = {}
  keys.map(key => {
    res[key] = obj[key]
  })
  return res
}
const nameAndAddress = pick(objPick, ['name', 'address'])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值