二、TypeScript的数据类型

70 阅读5分钟

JS和TS都有的类型

number类型

数字类型是我们开发中经常使用的类型,TypeScript和JavaScript一样,不区分整数类型(int)和浮点型(double),统一为number类型。

ES6新增了二进制和八进制的表示方法,而TypeScript也是支持二进制、八进制、十六进制的表示:

let num:number = 123
num=2

num=0b1101   //二进制
num=0o555   //八进制
num=0xf23   //十六进制

boolean类型

和JS一样,TS的boolean类型只有true/false两个值。

let flag:boolean = true
flag=20>30

string类型

string类型是字符串类型,可以使用单引号或者双引号表示:

let message:string = 'hello js'
message = "hello ts"

同时也支持ES6的模板字符串来拼接变量和字符串:

let hobby1:string="唱"
let hobby2="跳"
let hobby3="rap"

let hobbies=`my hobbies are ${hobby1},${hobby2},${hobby3}`

Array类型

数组里的元素类型可以通过以下两种方法声明:

let nums1: number[] = [1, 2, 3, 4]

let string1: Array<string> = ["ts","js"]  //Array<string>事实上是一种泛型的写法

object类型

根据类型推导可以推测出student以及其属性的类型。

image.png 如果不是使用类型推导而是直接通过student:object声明student是个对象类型后,我们不能获取student内数据,也不能设置数据:

image.png

null&undefined

在 JavaScript 中,undefined 和 null 是两个基本数据类型。

在TypeScript中,它们各自的类型也是undefined和null,也就意味着它们既是实际的值,也是自己的类型

image.png

值得一提的是null和undefined在非严格模式下可以赋值给string、number等类型的变量。但是如果let n:null 则表示n有且只有一个值那就是null

Symbol类型

在ES5中,如果我们是不可以在对象中添加相同的属性名称的,比如下面的做法: image.png

但是我们也可以通过symbol来定义相同的名称,因为Symbol函数返回的是不同的值:

image.png

image.png

TS添加的数据类型

any类型

在某些情况下,我们确实无法确定一个变量的类型,并且可能它会发生一些变化,这个时候我们可以使用any类型。

any类型有点像一种讨巧的TypeScript手段:

  • 我们可以对any类型的变量进行任何的操作,包括获取不存在的属性、方法;

  • 我们给一个any类型的变量赋值任何的值,比如数字、字符串的值;

image.png

如果对于某些情况的处理过于繁琐不希望添加规定的类型注解,或者在引入一些第三方库时,缺失了类型注解,这个时候 我们可以使用any, 包括在Vue源码中,也会使用到any来进行某些类型的适配;

unknow类型

unknown是TypeScript中比较特殊的一种类型,它用于描述类型不确定的变量。

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

let flag = true
let result: unknown // 最好不要使用any
if (flag) {
  result = foo()
} else {
  result = bar()
}

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

void类型

void通常用来指定一个函数是没有返回值的,那么它的返回值就是void类型: 我们可以将null和undefined赋值给void类型,也就是函数可以返回null或者undefined。

never类型

never 表示永远不会发生值的类型,比如一个函数是一个死循环或者抛出一个异常,所以不会有返回值,那么写void类型或者其他类型作为返回值类型都不合适,我们就可以使用never类型;

function handleMessage(message: string | number | boolean | any[]) {
  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:
      const check: never = message;
  }
}

就比如上面代码如果在联合类型添加一个any[]的数组类型,但是没有在switch语句加入对应的逻辑代码,那么就会跳到default,那么在编译过程中check:never这行就会报错,应为never类型的变量是不可能有赋值操作的。这样就起到了一个避免bug的作用。

tuple类型

tuple是元组类型,很多语言中也有这种数据类型,比如Python、Swift等。

那么tuple和数组有什么区别呢?

  • 首先,数组中通常建议存放相同类型的元素,不同类型的元素是不推荐放在数组中。(可以放在对象或者元组中)

  • 其次,元组中每个元素都有自己特性的类型,根据索引值获取到的值可以确定对应的类型;

const arr:any[] = ["jk", 18, 1.88]
const name = info[0]
console.log(name.length)  //name是any类型,虽然info[0]是个字符串也能够使用name.length,
//但是其他元素就不一定了,随意调取any类型的length属性,是十分危险的。

const info: [string, number, number] = ["jk", 18, 1.88]
const name = info[0]  //name是string类型,可以放心调取length属性。
console.log(name.length)

比如react的useState这个hook返回值就是一个数组,arr[0]是any类型,arr[1]是个函数并且没有返回值。这个时候使用元组就十分合适。

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")