导航


HTML

CSS

JavaScript

浏览器 & 网络

版本管理

框架

构建工具

TypeScript

性能优化

软实力

算法

UI、组件库

Node

冷门技能

数据类型

TS 中不用大写 Number、String、Boolean、Object

number 42 VS new Number(42)

Untitled

包装对象

const num = 42;
console.log(num.toFixed(2)); // '42.00'

上边代码所做操作:

  1. 发现 42 本身没有 toFixed 方法
  2. 临时包装 42 为 Number 对象,Number 对象下是有 toFixed 方法
  3. 调用 toFixed 获取 value
  4. 删除临时对象
  5. 返回 value

Untitled

结论

JS 中 Number、String、Boolean 只用于包装对象。一般情况下不用它们 在 TS 中也不用,而是用小写 number、string、boolean

大写的 Object 表示的范围太大,不推荐使用

const a: Object = /abc/
const b: Object = () => {}
const c: Object = []
const d: Object = 123 // 由于123可以包装成对象,所以不会报错

大写 Object 与 小写 object 区别

type A = Object
const a: A = 1
type B = object
const b: B = 1

Untitled

如何描述对象的数据类型

  1. class / constructor 描述
  2. typeinterface 描述
const fn: Function = () => {}
const arr: Array<number> = [1]
type Person = {
  name: string
  age: number
}
const p: Person = {
  name: 'Lance',
  age: 19,
}
type A = {
  [k: string]: number
}
// A 表示 key 为 string,value 为 number 的所有对象
// k 可以换成 任意单词
const a: A = {
  name: 1,
  123: 456, // 为什么键123是个数字也能通过?因为js中对象的键会被最终转为字符串
}

或者

type A = Record<string, number>
const a: A = {
  name: 233
}

Untitled

Untitled

结论

由于 Object 太不精确,所以 TS 开发者一般使用「索引签名」或「Record泛型」来描述普通对象

如何描述数组对象

const arr: Array<number> = [1, 2, 3]
type Two = [number, number] // 二元组
type Three = [string, string, number] // 三元组

Untitled

type A = [1, 2, 3]
const a: A = [1, 2, 3]
// 我们说 type number 是 1|2|3|3.1|... 的数字集合
// 那么我们把集合缩小到只有一个值1 它也是个集合 类型为1,只能填入1

如何描述函数对象

type FnA = (a: number, b: number) => number
// ts 松散参数类型检查,不定义 a,b 也能过检查
const a: FnA = () => {
  return 1
}
type FnReturnVoid = () => void
type FnReturnUndefined = () => undefined
const fn1: FnReturnVoid = () => {
  console.log('hi');
}
const fn2: FnReturnUndefined = () => {
  console.log('hi'); // 报错: 不能将类型“() => void”分配给类型“FnReturnUndefined”。不能将类型“void”分配给类型“undefined”
  return undefined; // 必须显示 return undefined, 否则报上述错误
}

带有 this 的函数声明

type Person = {
  name: string
  age: number
}

type FnWidthThis = (this: Person, name: string) => void // 限定 this 得为 Person 类

const sayHi: FnWidthThis = function() {
  console.log('hi ' + this.name);
}

const p: Person = {
  name: 'Lance',
  age: 28
}
sayHi.call(p, 'Jack')

其他对象一般用 class 描述

const d: Date = new Date()
const reg: RegExp = /abc/
const reg2: RegExp = new RegExp('abc', 'g')
const m: Map<string, number> = new Map()
m.set('age', 23)
const wm: WeakMap<{name: string}, number> = new WeakMap()
wm.set({name: 'Lance'}, 1)
const s: Set<number> = new Set()
s.add(123)

any、unknown

const p: any = 2333
const a: unknown = 10;
(a as number).toFixed(2)

never

enum

Untitled

enum Type {
  todo,
  done,
  archived,
  deleted
}

let state = 0
state = Type.todo
console.log(state);
enum Permission {
  None = 0,                     // 0000
  Read = 1 << 0,                // 0001
  Write = 1 << 1,               // 0010
  Delete = 1 << 2,              // 0100
  Mange = Read | Write | Delete // 0111
} // 左移右移 1 << 1 向左移动一位

type User = {
  permission: Permission
}
const user: User = {
  permission: 0b0010
}
if ((user.permission & Permission.Write) === Permission.Write) {
  // & 与 操作 (1&1 = 1, 0&? = 0)
  //    0010
  // &  0010
  // --------
  //    0010 相等
  console.log('拥有写权限');
}

何时选择 enum

Untitled

Untitled

Type 与 Interface

何时使用 Type

type Name = string
type FalseLike = '' | 0 | undefined | null | false
type Point = { x: number, y: number }
type Points = Point[]
type Line = [Point, Point]
type Circle = { center: Point; radius: number }
type Fn = (a: number, b: number) => number
type FnWidthProps = { // 声明一个带prop1属性的函数
    (a: number, b: number): number
    prop1: number
}
const fn: FnWidthProps = (x, y) => {
    return x + y
}
fn.prop1 = 233

注意点:限制类型的时刻

type A = {
  name: string
}
const a1: A = { // 声明时限制类型(严格检查)
  name: 'Lance',
  gender: '男'
}

// VS

type A = {
  name: string
}
const a1 = {
  name: 'Lance',
  gender: '男'
}
const a2 = {
  name: 'Lance',
  age: 24
}
const a: A = a1 // 声明后再限制

Untitled

何时使用 Interface

interface Data {
    [k: string]: string
}
interface Point {
    x: number;
    y: number;
}
interface Points extends Array<Point> {}
interface Fn {
    (a: number, b: number): number
    xxx: number
}
const f: Fn = (x, y) => { return x + y }
f.xxx = 100
interface Date2 extends Date {}
type A1 = Array<string> & {
    name: string
} & X

interface X {
    age: number
}

interface A2 extends Array<string>, X {
    name: string
}

Untitled

区别

  1. interface 只描述对象;type 则描述所有数据
  2. type 只是别名;interface 则是个自定义的新的类型
    1. 由下边两个截图可看出,type只是别名;而interface定义后相当于一种类型被保存了下来

Untitled

Untitled

  1. type 不可被重新赋值和覆盖;interface 则可扩展合并(可在 interface 上继续拓展属性,能自动合并)
interface X {
  name: string
}
interface X {
  age: number
}
const p: X = {
  name: 'Lance',
  age: 29
}
import { AxiosRequestConfig } from "axios'

declare module 'axios' {
	export interface AxiosRequestConfig {
    _autoLoading?: boolean
		_mock?: String
  }
}
declare global {
  interface String {
    padZero(x: string): void
  }
}

const s = 'hello'
s.padZero('hello')

export {}

总结