前文回顾
- Vue & TypeScript 初体验
- Vue & TypeScript 初体验 - 使用Vuex (vuex-module-decorators)
- Vue & TypeScript 初体验 - TypeScript中的Interface
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 比较常见:
- 抛出异常的函数永远不会有返回值
function error(msg: string): never {
throw new Error(message);
}
- 空数组,而且永远是空的
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 ''
}