Typescript实用指南

TOC

没有TS时的困扰

less 复制代码
张三: 你知道下面的这个test方法要如何传参吗?
胖虎: 传a,b两个参数
张三: 具体呢?你知道a,b是什么类型吗?
胖虎: 你一没注释,二又看不到代码具体内容,我怎么知道a,b什么类型?你是在为难我胖虎啊
张三: 要注释? 没问题,继续往下看
js 复制代码
function test(a,b){
    ...
}
less 复制代码
张三: 再看看这个,注释,代码都有了,告诉我a,b如何传参
胖虎: 找茬呢,这注释有和没有有区别吗?还有这代码,还要我通读,还要我根据代码推敲这个参数的意思和类型,不想写就别写啊
js 复制代码
/**
* @params {Object} a 第一个参数
* @params {Object} b 第二个参数
*/
function test(a,b){
    const {flag,good} = b
    ...省略若干代码
    if(b.test){
        ...省略若干代码
    }
}

没错这就是前端项目在没有TS时,大概率会遇到的问题,别人写的方法具体如何调用?后端接口返回的参数到底是什么接口? 不知道,在不运行到具体代码行,不一行行阅读源码,大概率是不知道的

基础

与JS基本数据类型对应的TS类型定义

字符串

ts 复制代码
let str:string = ''

数值

ts 复制代码
let num:number = 1

布尔值

ts 复制代码
let flag:boolean = true

数组

ts 复制代码
const arr1: Array<string> = []
const arr2: Array<string|number> = []
const arr3: [string,number] = ['a',1]

日期

ts 复制代码
const date: Date = new Date()

null与undefined

ts 复制代码
const x1: null = null
let x2: undefined;

symbol

ts 复制代码
const sym: Symbol = Symbol()
const symb: Symbol = Symbol('abc')

Map类型

ts 复制代码
const map = new Map<string,number>()

对象

ts 复制代码
const obj: Record<string, any> = {}

interface Person {
  name: string
  age: number
}

const p:Person = {
    name:"张三",
    age:12
}

函数

ts 复制代码
function test(a: number, b: number): number {
  return a + b
}
ts 复制代码
function test(a: string, b: string): number
function test(a: number, b: number): number

function test(a: number | string, b: number | string): number {
  const numA: number = typeof a === 'string' ? Number(a) : a
  const numB: number = typeof b === 'string' ? Number(b) : b
  return numA + numB
}

test('1', '2')
test(4, 3)
ts 复制代码
type TestFun = (a: number, b: number) => number
const fun: TestFun = (a, b) => {
  return a + b
}
ts 复制代码
interface TestFun {
  (x: number, y: number): number
}
const fun: TestFun = (x, y) => {
    return x+y
}

复合类型

ts 复制代码
interface PartA {
  name: string
  fatherName: string
}
interface PartB {
  age: number
  male: boolean
}

type PartC = PartA & PartB
type PartD = PartA | PartB

const partC: PartC = {
  name: '',
  fatherName: '',
  age: 0,
  male: false
}

const partD: PartD = {
  name: '',
  fatherName: ''
}

获取对象中所有key作为类型定义

ts 复制代码
interface PartA {
  name: string
  fatherName: string
}

type PartAKeys = keyof PartA

const keyFahter: PartAKeys = 'fatherName'
const keys: PartAKeys = 'name'

抽取特定接口定义的部分属性,作为一个新类型

ts 复制代码
interface Person {
  name: string
  age: number
  male: boolean
}

// 使用Person接口的name,male形成一个新接口
type NewPerson = Pick<Person, 'name' | 'male'>

const person: Person = { name: '张三', age: 12, male: true }
const newPerson: NewPerson = { name: '张三', male: true }

排除特定接口定义的部分属性,作为一个新类型

ts 复制代码
interface Person {
  name: string
  age: number
  male: boolean
}

// 将Person接口,排除age属性之后,形成一个新接口
type NewPerson = Omit<Person, 'age'>

const person: Person = { name: '张三', age: 12, male: true }
const newPerson: NewPerson = { name: '张三', male: true }

以特定接口为基础进行扩展

ts 复制代码
interface Person {
  name: string
  male: boolean
}

interface NewPerson extends Person {
  age: number
}

const p: Person = {
  name: '',
  male: true
}

const p1: NewPerson = {
  name: '',
  male: true,
  age: 0
}

泛型

指定this类型

ts 复制代码
type Service<R, P extends unknown[]> = (...args: P) => Promise<R>
function wrapper<R, P extends unknown[]>(service: Service<R, P>) {
  return function (this: any, ...args: P) {
    const method = service.bind(this)
    return method(...args)
  }
}

function test(a: number, b: number): Promise<number> {
  return Promise.resolve(a + b)
}

const wrapperTest = wrapper(test)

;(async () => {
  console.log(await wrapperTest(1, 2))
})()
ts 复制代码
/**
 *
 * @param this 指定this类型,必须为第一个参数
 * @param str 从这个参数开始,才是这个方法的实际参数
 */
function doAdd(this: Plus, str: string) {
  const ret = this.a + this.b
  console.log(str, ret)
}
class Plus {
  a: number = 0
  b: number = 0

  constructor(a: number, b: number) {
    this.a = a
    this.b = b
  }

  add = doAdd
}

new Plus(1, 3).add('hello')

any, unknow

any和unknow都表示任意类型,但unknow要求,在使用unknow声明的变量时,必须先转换为某个具体的类型

void, never

可变参数类型

不确定的可变参数类型通过此种方式指定

ts 复制代码
type Service<R, P extends unknown[]> = (...args: P) => Promise<R>
function wrapper<R, P extends unknown[]>(service: Service<R, P>) {
  return function (this: any, ...args: P) {
    const method = service.bind(this)
    return method(...args)
  }
}

function test(a: number, b: number): Promise<number> {
  return Promise.resolve(a + b)
}

const wrapperTest = wrapper(test)

;(async () => {
  console.log(await wrapperTest(1, 2))
})()

禁止TS报错

ts 复制代码
单行忽略
// @ts-ignore

忽略全文
// @ts-nocheck

取消忽略全文
// @ts-check
ts 复制代码
/* eslint-disable */
const watermark = require("watermark-dom"); // @ts-ignore
/* eslint-enable */

便捷操作

ts 复制代码
const obj: Record<'x1' | 'x2' | string, string | number> = {
  x1: '你好',
  x2: '世界',
  name: '张三'
}

实际项目快速应用TS定义

从json字符串生成TS

JSON to TS - Visual Studio Marketplace

从swagger生成TS

tswagger - Visual Studio Marketplace

swagger-to-ts-fix - Visual Studio Marketplace

swagger-to-ts - Visual Studio Marketplace

JS To TS - Visual Studio Marketplace

vue3项目中的TS

组件事件: defineEmits

TypeScript 与组合式 API | Vue.js (vuejs.org)

泛型组件

相关推荐
一斤代码2 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子2 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年2 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子3 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina3 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路4 小时前
React--Fiber 架构
前端·react.js·架构
伍哥的传说4 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
qq_424409194 小时前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app
我在北京coding4 小时前
element el-table渲染二维对象数组
前端·javascript·vue.js
布兰妮甜4 小时前
Vue+ElementUI聊天室开发指南
前端·javascript·vue.js·elementui