Vue & TypeScript 初体验 - TypeScript中常用的数据类型

226 阅读4分钟

前文回顾

TypeScript新增类型

TypeScript是JavaScript的超集, 相比于JavaScript, 新增了一些类型:

  • tuple, 元组
  • enum, 枚举
  • any
  • void
  • never

1. 基本类型

基本数据类型有:

  • number, 数字
  • string, 字符串
  • undefined
  • null
  • boolean
  • symbol

number

// string
let nickname: string = 'james'
let templateStr: string = `Hello ${nickname}`

string

// number
let sum: number = 6
let hexIteral: number = 0xf00d

undefined

// undefined
let undef: undefined = undefined

null

// null
let n: null = null

boolean

// boolean
let isShow: boolean = true

symbol

Symbol是在ES2015之后成为新的原始类型, 它通过Symbol构造函数创建唯一不变的值

// symbol
let s:symbol = Symbol('james');
Symbol('james') === Symbol('james') // false

2. 特殊类型

  • enum, 枚举
  • array, 数组
  • object, 对象
  • tuple, 元组
  • any, 任意类型
  • unknown, 未知类型
  • void, 无返回值
  • never, 永无返回值

enum

枚举类型是很多语言都拥有的类型,它用于声明一组命名的常数,当一个变量有几种可能的取值时,可以将它定义为枚举类型。

例如:

enum Sex {
  man = 1,
  woman = 2
}
let sex: Sex = Sex.man

enum HttpCode {
    success = 200,
    fail = 500
}

array

数组有两种定义方式, 一种是使用泛型, 如:

const arr:Array<number> = [0, 1, 2]

一种是在元素类型后加上[], 是最常用的方式.

const arr:number[] = [0, 1, 2]

tuple

元组, 表示一个已知元素数量和类型的数组,各元素的类型不必相同。例如:

const tuple: [number, string, string] = [30, 'hello', 'james']

元组和数组很相似(元组继承自数组), 但元组非常严格, 即元素的数量或类型的顺序不一致, 都会报错.

const tuple: [number, string, string] = ['hello', 'hello', 'james'] // Error

const tuple: [number, string, string] = [30, 'hello'] // Error

object

object 表示非原始类型,即除 number,string,boolean,symbol,null 或 undefined 外的类型。

enum Direction {
    Center = 1
}

let value: object

value = Direction
value = [1]
value = [1, 'hello']
value = {}

any

any一般适用于: 值来源于动态内容的, 如用户输入或第三方代码库

注意, any类型是多人协作项目的禁忌, 通常情况下不考虑使用此类型(万不得已时才可使用)

let fullname: any = 'jameszhang'
fullname = 20
fullname = { nickname: 'hello jameszhang' }

unknown

unknown 是TypeScript 3.0引入了新类型,是 any 类型对应的安全类型。

unknown 和 any 的主要区别是:

  • unknown 类型会更加严格, 在对unknown类型的值执行大多数操作之前,我们必须进行某种形式的检查
  • any 类型的值执行操作之前,不必进行任何检查。

unknown和any的相同点:

let value: any
value = true // OK
value = 1 // OK
value = 'Hello World' // OK
value = Symbol('type') // OK
value = {} // OK
value = [] // OK

let value1: unknown

value1 = true // OK
value1 = 1 // OK
value1 = 'Hello World' // OK
value1 = Symbol('type') // OK
value1 = {} // OK
value1 = [] // OK

unknown和any的不同点在于, 当unknown类型被确定是某个类型前, 它不能被进行任何操作, 如: 实例化、getter、函数执行等.

let value2: any
value2.foo.bar // OK
value2() // OK
new value2() // OK
value2[0][1] // OK

let value3: unknown
value3.foo.bar // ERROR
value3() // ERROR
new value3() // ERROR
value3[0][1] // ERROR

可以看出, unknown会比any更安全, 如果使用any, 很容易犯一些低级错误, 因此, 在很多不确定类型的场景中, 可以优先使用unknown类型, 例如:

function getString(val:unknown):string {
  if(val instanceof Date) {
    return val.toLocaleDateString();
  }
  return String(val);
}

void

表示没有任何类型, 即一个函数没有任何返回wfhg.例如:

function log(msg: string): void {
  window.console.log(msg)
}

注意: 只有null和undefined可以赋给void, 例如:

const v: void = undefined

never

never 类型表示的是那些永不存在的值的类型,never 类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是 never 的子类型或可以赋值给 never 类型(除了never本身之外)。

即使any也不可以赋值给never

两个场景中 never 比较常见:

  1. 抛出异常的函数永远不会有返回值
function error(msg: string): never {
    throw new Error(message);
}
  1. 空数组,而且永远是空的
const empty: never[] = []

3. 类型断言

有些情况下 TS 并不能正确或者准确得推断类型,这个时候可能产生不必要的警告或者报错。

比如初学TypeScript时, 可能会常犯如下一类错误:

const person = {};

person.name = 'james'; // Error, 类型'{}'上不存在"name"属性
person.age = 20; // Error, 类型'{}'上不存在"age"属性

为何会报错呢? 因为TypeScript认为person声明时的类型为{}, 并不存在后面添加的属性, 因此会报错.

在JavaScript编码中, 可能会经常写这样的代码.

此时, 可能就需要使用类型断言了.

interface Person {
  name: string;
  age: number;
}
const person = {} as Person;

person.name = 'james';
person.age = 20;

类型守卫

class Cat {
  getName(): string {
    return 'hello world'
  }
}
class Dog {
  name: string = 'dog'
}
// instanceof
function getName(d: Dog | Cat): string {
  if (d instanceof Cat) {
    return d.getName()
  }
  if (d instanceof Dog) {
    return d.name
  }
  return ''
}
// in
function getName1(d: Dog | Cat): string {
  if ('getName' in d) {
    return d.getName()
  }
  if ('name' in d) {
    return d.name
  }
  return ''
}

相关链接