typescript 的类型分为用户类型和系统类型,而系统类型中又有基础类型和特殊类型、以及一部分高级类型,要运用好typescript,则必须要弄明白typescript中类型机制,在这章内容中,我们先来讲一下typescript中的特殊类型。
any 类型
这个逻辑很好理解,很简单,你只需要知道any与任意类型都是兼容的,而且这个兼容是双向的,如果把typescript中的任何需要类型的地方都标注为any
,它将与js没有任何区别。在我们未在tsconfig.json
中用选项noImplicitAny: true
关闭隐式any类型时,任何没有标注类型的地方,都是any
类型,否则需要主动添加类型声明以避免报错。
【示例】:
type IsAnyExtendsString = any extends string ? true : false; // true
type isStringExtendsAny = string extends string ? true : false; // true
以上示例中的 string
可以替换成任意类型,均能返回true结果
object 类型
object
是一个极易产生误解的东东,许多人起初认为object
是Object
的另名(我也不例),而且用起来似乎也真是那么回事。但是,object
准确定义是——除了基础类型以外的任意类型,下面我们再来讲讲他们有什么不同。
object
类型与Object
类型与{}
类型的区别:
我们知道Object
在当作值使用的时候,表示的是JS中的Object对象构造函数,而当作类型使用的时候,则是表示Object类型本身,它包含了Object所具有成员,如toString
等
我们再来说一下{},{}表示的是一个不带任何约束的类型,因此它可以接受某些特殊类型(如void)以外的任何类型的值,但不一定能接受。
看看以下示例:
// object类型
let x: object = {}
let y: number = 1
x = y // error
y = x // error
// {}类型
let x: {} = {}
let y: number = 1
x = y // ok
y = x // error
// Object类型
let x: Object = {}
let y: number = 1
x = y // ok
y = x // error
看完这个示例,我们应该就能明白object与{}的区别了,object类型并不兼容基础类型,而{}
类型则可以接受几乎所有类型的值。Object
类型是带有整个原型链的属性的,如Object.prototype.toString()
,我们把它当作一个class看待即可。
{}
值与{}
类型:
在JS里,我们只需声明一个{}
对象即可随意添加成员使用,如:
// JS代码
const obj = {}
obj.a = 1
因此很多用习惯了JS的朋友会把值{}
的类型与以下类型混淆:
// TS代码
export type Dictionary = {
[key: string]: any
}
事实上我们在TS中声明一个{}
值,类型推导系统推导出来的类型是Object
类型,因为值{}
是从Object
构造函数中实例化的
const obj = {};
obj.a = 1; //error
正确的写法是:
const obj: Dictionary = {}
obj.a = 1
unknown 类型
unknown表示一个没有任何约束的类型,它可以授受任意类型的值。看过上一节的朋友是不是有种很熟悉的感觉?是的,没错,它几乎等价于{}
类型,唯一的区别是unknow
可以接受任意类型的值,包括void
之类的特殊类型。
void 类型
void
类型通常用来表示没有返回值的函数返回类型,而函数的默认返回值为undefined
,因此它被设计为不可以接受除undefined
与any
以外的任意类型的值。是不是听上去与undefined
类型很相似?其实不然,在未启用strictNullChecks
时,undefined
与null
类型可以作为右值赋给任意类型变量,而void
类型不可以赋给除any
以外的任意类型。