TypeScript

225 阅读3分钟

将ts编译成js的方法:

  1. webpack + babel
  2. Vite 2
  3. tsc ( typescript compiler )

使用vite2

vite/packages/create-vite at main · vitejs/vite

  1. create-vite-app ts-demo --template react-ts
  2. yarn
  3. yarn dev

类型 vs 类

类型 type

JS基本类型:null、undefined、string、boolean、number、symbol、bigint、object

typeof 有两个bug:

  1. typeof 函数 === function
  2. typeof null === object

类 class

JS 中的类只研究8种类型种的object,类是人为发明的

面向对象编程有两种:

  1. 基于class关键字
  2. 基于原型

类型的两个好处

  1. 减少bug
  2. 智能提示

Typescript语法

支持js的8个类型

const a:undefined = undefined const b:null = null const c:string = 'hi' const d:boolean = true const e:symbol = Symbol('hi') const f:bigint = 123n const obj:object = {} const arr:Array<string|number|null> = ['1', '2', 3, null]

函数有四种写法:

  1. 类型写在函数体
const add = (a:number, b:number):number => a + b
  1. :后面
const add:(a:number, b:number)=>number = (a, b)=> a + b
  1. type缩写
type Add = (a:number, b:number) => number
const add:Add = (a,b) => a+b
  1. 有属性,只能用 interface
interface AddWithProps {
  (a:number, b:number):number 
  xxx: string
}
const add:AddWithProps = (a,b) => a+b
add.xxx = 'xxx'

typescript自己的类型

1、any 可以是任何类型

let a:any = 'hi'
a.name
a = 1

2、unknown 用时需要明确是什么类型

type C = {name: string}
type E = {age:number}
let b: unknown = JSON.parse('{"name": "frank"}')
console.log((b as C).name)  // 断言
console.log((b as E).name)  // 报错

3、void 描述函数,不要写return

let print: (a:number) => void = function(a){
  console.log(a)
}

4、never

let c: never = null                   //报错
let c: never = undefined              //报错
console.log(c)                        //报错

never 类型不能赋值,不能使用

那有什么用?

如果你的代码中让一个东西变成never,说明你的代码出错了,举例说明

type Dir = 1 | 2 | 3 | 4 | undefined
let dir: Dir = 1
switch(dir){

}

所以 never 就是不应该存在的,或者就是没有的

type X = number & string   

X 的类型就是never

5、元组

let p: [number, number] = [100, 200]
p = [1,2,3,4]    // 报错

6、枚举

enum Color {Red, Green, Blue}
let c: Color = Color.Green;
console.log(c)                // 1

下面写法类似

type Dir = '东' | '南' | '西' | '北'
let dir:Dir = '东'
console.log(dir)   // 东

class

Object、Array、Function

class是值也是类型

联合类型 |

type A = {
  name: string,
  age: number
}
type B = {
  name: string,
  gender: string
}
const f = (n:number | B) => {
  if(typeof n === 'number'){
    n.toFixed()
  }else{
    n.name
  }
}

收窄类型:

type A = {
  name: 'a',
  age: number
}
type B = {
  name: 'b',
  gender: string
}
const f = (n: A | B) => {
  if(n.name === 'a'){
    n.age
  }else{
    n.gender
  }
}

交叉类型 &

& 不能用于简单类型 如 type A = number & string A 类型为 never

type A = {name:string} & {age: number}   
const a:A = {
  name: 'frank',     // name 和 age 都要写,不然报错
  age: 18
}

如果两边都有age,A为never

type A = {name:string, age: string} & {age: number}   

泛型

type Add<T> = (a: T, b: T) => T
const addN: Add<number> = (a,b) => a + b
const addS: Add<string> = (a,b) => a + ' ' + b

泛型的实际应用

import React, {FunctionComponent} from 'react'

type P = {
  name: string
}
const app: FunctionComponent<P> = (props)=>{
  props.name
  props.children
  return <div>hi</div>
}

重载

例子1: 实现当a,b为number时,return a + b

当a,b为string时,return a + ' ' + b

Snipaste_2021-12-21_10-54-43.png

例子2:

type Options = {headers?: any}
function get(url: string, options?: Options): void
function get(options: Options & {url: string}): void
function get(url: string | (Options & {url:string}), options?: Options):void{
  if(arguments.length === 1){
    const myOptions = url as {url: string} & Options
    console.log(myOptions.url);
    console.log(myOptions.headers);
  }else{
    console.log((url as string))
  }
}
get('/xxx', {headers: 'get'})
get({url:'/xxx', headers:'get'})

如何用泛型封装网络请求库

type User = {
  id: string | number;
  name: string;
  age: number;
}
type Response<T> = {
  data:T
}
type T = Partial<Omit<User, 'id'>>
type CreateResource = (path: string) => {
  create: (attrs:Omit<Partial<User>, 'id'>) => Promise<Response<User>>;
  delete: (id: User['id']) => Promise<Response<never>>;
  update: (id:User['id'], attrs: Omit<Partial<User>, 'id'>) => Promise<Response<User>>;
  get: (id: User['id']) => Promise<Response<User>>;
  getPage: (page: number) => Promise<Response<User[]>>;
}
const createResource = (path:string)=>{
  return {
    create(attrs: Omit<Partial<User>, 'id'>){
      const url = path + 's'
      return axios.post<User>(url, {data: attrs})
    },
    delete(){},
    update(){},
    get(){},
    getPage(){}
  }
}

var userResource = createResource('/api/v1/user')