• 周一. 8月 15th, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

694 TypeScript类型:any,unknown,void,never,tuple,函数的参数、返回值,匿名函数的参数,对象,可选,联合,类型别名,类型断言as,非空类型断言!,可选链,??和!!,字面量,字面量推理,类型缩小

admin

11月 28, 2021

TypeScript类型 – any类型


TypeScript类型 – unknown类型


TypeScript类型 – void类型


TypeScript类型 – never类型


TypeScript类型 – tuple类型


Tuples的应用场景


01_any类型的使用.ts

// 当进行一些类型断言 as any
// 在不想给某些JavaScript添加具体的数据类型时(原生的JavaScript代码是一样)
let message: any = 'Hello World'

message = 123
message = true
message = {}

// message()
// message.split(" ")

console.log(message)
const arr: any[] = [] // 【不推荐】

02_unknown类型的使用.ts

function foo() {
  return 'abc'
}

function bar() {
  return 123
}

// unknown类型只能赋值给any和unknown类型
// any类型可以赋值给任意类型

let flag = true
let result: unknown // 最好不要使用any

if (flag) {
  result = foo()
} else {
  result = bar()
}

// 补充
let aaa: any = result
let bbb: unknown = result

// let message: string = result
// let num: number = result

console.log(result) // abc
console.log(aaa) // abc
console.log(bbb) // abc

export {}

03_void类型的使用.ts

// 【此时,void可以省略不写。】
function sum(num1: number, num2: number) {
  console.log(num1 + num2)
}

sum(20, 30)
// sum("abc", "cba")

04_never类型的使用.ts

// function foo(): never {
//   // 死循环
//   while(true) {

//   }
// }

// function bar(): never {
//   throw new Error()
// }

// 提前
// 封装一个核心函数
function handleMessage(message: string | number | boolean) {
  switch (typeof message) {
    case 'string':
      console.log('string处理方式处理message')
      break
    case 'number':
      console.log('number处理方式处理message')
      break
    case 'boolean':
      console.log('boolean处理方式处理message')
      break
    default:
      // 【增加boolean类型后,check报错,这样防止别人增加boolean类型后,不在函数体中编写对应的代码。】
      // 【上面的case判断已经把所有的情况穷举完,代码不会执行到default中,message才会赋值给never类型的check。】
      const check: never = message
  }
}

handleMessage('abc')
handleMessage(123)

// 张三
handleMessage(true)


05_tuple类型的使用.ts

// tuple元组: 多种元素的组合
// "why" 18 1.88

// 1.数组的弊端
// const info: any[] = ["why", 18, 1.88]
// const infoObj = {
//   name: "why",
//   age: 18,
//   height: 1.88
// }

// const name = info[0]
// console.log(name.length)


// 2.元组的特点
const info: [string, number, number] = ["why", 18, 1.88]
const name = info[0]
console.log(name.length)
// const age = info[1]
// console.log(age.length)

export {}

06_tuple的应用场景.ts

// hook: useState
// const [counter, setCounter] = {counter: , setCounter:}

function useState(state: any) {
  let currentState = state
  const changeState = (newState: any) => {
    currentState = newState
  }

  const tuple: [any, (newState: any) => void] = [currentState, changeState]
  return tuple
}

const [counter, setCounter] = useState(10);
setCounter(1000)

const [title, setTitle] = useState("abc")

export {}

07_tuple的应用场景(优化).ts

// hook: useState
// const [counter, setCounter] = {counter: , setCounter:}

function useState<T>(state: T) {
  let currentState = state
  const changeState = (newState: T) => {
    currentState = newState
  }
  const info: [string, number] = ['abc', 18]
  const tuple: [T, (newState: T) => void] = [currentState, changeState]
  return tuple
}

const [counter, setCounter] = useState(10)
setCounter(1000)
const [title, setTitle] = useState('abc')
const [flag, setFlag] = useState(true)

// type MyFunction = () => void
// const foo: MyFunction = () => {}

函数的参数类型


函数的返回值类型


匿名函数的参数


对象类型


可选类型


联合类型


使用联合类型


可选类型补充


类型别名


01_函数的参数和返回值类型.ts

// 给参数加上类型注解: num1: number, num2: number
// 给返回值加上类型注释: (): number
// 在开发中, 通常情况下可以不写返回值的类型(自动推导)
function sum(num1: number, num2: number) {
  return num1 + num2
}

// sum(123, 321)

02_匿名函数的参数类型.ts

// 通常情况下, 在定义一个函数时, 都会给参数加上类型注解的
function foo(message: string) {}

const names = ['abc', 'cba', 'nba']
// item根据上下文的环境推导出来的, 这个时候可以不添加的类型注解
// 上下文中的函数: 可以不添加类型注解 【自动类型推导。】
names.forEach(function (item) {
  console.log(item.split(''))
})

03_对象类型.ts

// Point: x/y -> 对象类型
// {x: number, y: number}
function printPoint(point: { x: number; y: number }) {
  console.log(point.x)
  console.log(point.y)
}

printPoint({ x: 123, y: 321 })

export {}

04_可选类型.ts

// Point: x/y/z -> 对象类型
// {x: number, y: number, z?: number}
function printPoint(point: { x: number; y: number; z?: number }) {
  console.log(point.x)
  console.log(point.y)
  console.log(point.z)
}

printPoint({ x: 123, y: 321 })
printPoint({ x: 123, y: 321, z: 111 })

export {}

05_联合类型.ts

// number|string 联合类型
function printID(id: number | string | boolean) {
  // 使用联合类型的值时, 需要特别的小心
  // narrow: 缩小
  if (typeof id === 'string') {
    // TypeScript帮助确定id一定是string类型
    console.log(id.toUpperCase())
  } else {
    console.log(id)
  }
}

printID(123)
printID('abc')
printID(true)

06_可选类型和联合类型的关系.ts

// 让一个参数本身是可选的
// 一个参数一个可选类型的时候, 它其实类似于是这个参数是 类型|undefined 的联合类型
// function foo(message?: string) {
//   console.log(message)
// }

function foo(message?: string) {
  console.log(message)
}

foo()

07_类型别名.ts

// type:用于定义类型别名(type alias)
type IDType = string | number | boolean

type PointType = {
  x: number
  y: number
  z?: number
}

function printId(id: IDType) {}

function printPoint(point: PointType) {}

类型断言as


非空类型断言!


可选链的使用


??和!!的作用


字面量类型


字面量推理


类型缩小


typeof


平等缩小


instanceof


in


01_类型断言as.ts

// <img id="why"/>

// 1.类型断言 as 【从宽泛的HTMLElement中指定为具体的HTMLImageElement,这样就可以使用具体的类型中的属性、方法了。】
const el = document.getElementById('why') as HTMLImageElement
el.src = 'url地址'

// 2.另外案例: Person是Student的父类
class Person {}

class Student extends Person {
  studying() {
    console.log('study harding')
  }
}

function sayHello(p: Person) {
  ;(p as Student).studying()
}

// 补充:这样写就不用使用as了,传入Student,而不是Person
function sayHello2(p: Student) {
  p.studying()
}

const stu = new Student()
sayHello(stu)

// 3.了解: as any/unknown 【不推荐,除了特殊情况。】
const message = 'Hello World'
const num: number = message as unknown as number

02_非空类型断言.ts

// message? -> undefined | string
function printMessageLength(message?: string) {
  // if (message) {
  //   console.log(message.length)
  // }
  // vue3源码 【确定某个标识符是有值的,跳过ts在编译阶段对它的检测,告诉tsc这个message是有值的,不用判断是否为空。】
  console.log(message!.length)
}

printMessageLength('aaaa')
printMessageLength('hello world')

03_可选链的使用.ts

type Person = {
  name: string
  friend?: {
    name: string
    age?: number
    girlFriend?: {
      name: string
    }
  }
}

const info: Person = {
  name: 'why',
  friend: {
    name: 'kobe',
    girlFriend: {
      name: 'lily',
    },
  },
}

// 另外一个文件中 【问号?:表示可能有,也可能没有,如果没有会逻辑短路,不再执行后面的代码,直接返回undefined。】
console.log(info.name)
// console.log(info.friend!.name)
console.log(info.friend?.name)
console.log(info.friend?.age)
console.log(info.friend?.girlFriend?.name)

// if (info.friend) {
//   console.log(info.friend.name)

//   if (info.friend.age) {
//     console.log(info.friend.age)
//   }
// }

04_!!运算符.ts

const message = "Hello World"

// const flag = Boolean(message)
// console.log(flag)

const flag = !!message
console.log(flag)

05___运算符.ts

let message: string | null = 'Hello World'

const content = message ?? '你好啊, 哈哈'
// 【类似于逻辑或|| ,以及三目运算的简化。】
// const content = message ? message: "你好啊, 哈哈"
console.log(content)

// 补充
let msg1: string | null | undefined = 'aaa'
let msg2: string | null | undefined = null
let msg3: string | null | undefined = undefined

let res1 = msg1 ?? 'haha'
let res2 = msg2 ?? 'xixi'
let res3 = msg3 ?? 'hehe'

console.log(res1, res2, res3) // aaa xixi hehe

export {}

06_字面量类型.ts

// "Hello World"也是可以作为类型的, 叫做字面量类型
const message: 'Hello World' = 'Hello World'

// 【字面量类型:值和类型要一致,不能修改。】
// let num: 123 = 123
// num = 321

// 字面量类型的意义, 就是必须结合联合类型
type Alignment = 'left' | 'right' | 'center'

let align: Alignment = 'left'
align = 'right'
align = 'center'

// align = 'hehehehe'

07_字面量推理.ts

// const info = {
//   name: "why",
//   age: 18
// }

// info.name = "kobe"

type Method = 'GET' | 'POST'

function request(url: string, method: Method) {}

// 【方法1:推荐这种做法,一开始就把类型规定好。】
type Request = {
  url: string
  method: Method
}

// 【方法2:as const 在这里叫字面量推理,里面的属性就是只读了。】
const options = {
  url: 'https://www.haha.org/abc',
  method: 'POST',
} as const

// const options = {
//   url: 'https://www.haha.org/abc',
//   method: 'POST',
// }

// 【ts认为options.method就是字符串,不一定是 'GET' | 'POST',所以报错。】
request(options.url, options.method)

// 方法3:as Method 【个人觉得这种方法最简单,as规定options.method为Method即可。】
// request(options.url, options.method as Method)

export {}

08_类型缩小.ts

// 1.typeof的类型缩小
type IDType = number | string

function printID(id: IDType) {
  if (typeof id === 'string') {
    console.log(id.toUpperCase())
  } else {
    console.log(id)
  }
}

// 2.平等的类型缩小(=== == !== !=/switch)
type Direction = 'left' | 'right' | 'top' | 'bottom'

function printDirection(direction: Direction) {
  // 1.if判断
  // if (direction === 'left') {
  //   console.log(direction)
  // } else if ()
  // 2.switch判断
  // switch (direction) {
  //   case 'left':
  //     console.log(direction)
  //     break;
  //   case ...
  // }
}

// 3.instanceof
function printTime(time: string | Date) {
  if (time instanceof Date) {
    console.log(time.toUTCString())
  } else {
    console.log(time)
  }
}

class Student {
  studying() {}
}

class Teacher {
  teaching() {}
}

function work(p: Student | Teacher) {
  if (p instanceof Student) {
    p.studying()
  } else {
    p.teaching()
  }
}

const stu = new Student()
work(stu)

// 4. in
type Fish = {
  swimming: () => void
}

type Dog = {
  running: () => void
}

function walk(animal: Fish | Dog) {
  if ('swimming' in animal) {
    animal.swimming()
  } else {
    animal.running()
  }
}

const fish: Fish = {
  swimming() {
    console.log('swimming')
  },
}

walk(fish)

发表回复

您的电子邮箱地址不会被公开。