一系列值及可以对齐执行的操作
typescript
类型层次结构
Unknow
Undefined Void Any Null
Number Bigint Boolean String Symbol Object
Never
Object
Array Function Constuctor
Tuple
类型浅谈
Any
any
是类型的教父.
any
包含所有的值,而且可以对其做任何操作.
不应该轻易使用any
,使用时应该显式注解.
Unknown
他吊儿郎当,与坏人同流合污,但是内心却尊重法律,站在好人这边
.
在少数情况下,如果你确实无法预知一个值的类型,不要使用any
,应该使用unknown
.与any
类似,unknown
也表示任何值,但是Typescript
会邀请你再做检查,细化类型.
unknown
类型支持比较(使用==,===,||,&&,?
),可以使用否定(!
),可以使用typeof
和instanceof
运算符细化.
- Typescript不会把任何值推导为
unknown
类型,必须显示注解 unknown
的值可以比较- 执行操作时不能假定
unknown
类型的值为某种特定类型,必须先向Typescript证明一个值确实是某个类型
Boolean
let a = true // boolean
var b = false // boolean
const c = true // true
let e:true = true // true
let f:true = false // Error
把类型设为某个值,就限制e
和f
的在所有的boolean
值中只能取指定的那个值,这个特性称为类型字面量(type literal)
类型字面量: 只表示一个值的类型
使用const
声明的基本类型的值,赋值之后便无法修改,因此Typescript推导出的是范围最窄的类型(f
)
Number
(略)
number
类型表示的最大整数为 2^53
BigInt
bigint
是JavaScript和TypeScript新引入的类型,在处理较大的整数时,不用担心舍入误差.
String
(略)
Symbol
(略)
对象
TypeScript的对象类型表示对象的结构.
结构化类型: 一种编程设计风格,只关心对象有哪些属性,而不管属性使用什么名称(名义化类型).也叫鸭子类型
- 对象字面量语句声明对象
let a={
b:'x'
} // {b:string}
a.b :string
// 也可以显示注解
let a:{b:number} = {
b:12
} // {b:number}
对象字面量句法的意思是:这个东西的结构是这样的,这个东西可能是一个对象字面量,也可能是一个类:
let c:{
firstName:string
lastName:string
} = {
firstName:'john',
lastName:'barrowman'
}
class Person {
constructor(public firstName:string,public lastName:string)
{
}
}
c = new Person('matt','smith') // ok
{ firstName:string,lastName:string}
描述的是一个对象的结构,上述示例的对象字面量和类实例都满足该结构,因此TypeScript允许把一个Person
实例赋值给c
.
可选属性
let a:{
b:number ①
c?:string ②
[key:number]:boolean ③
}
① a
有个类型为number
的属性b
② a
可能有个类型为string
的属性c
.如果有属性c
,其值可以为undefined
③ a
可能有任意多个数字属性,其值为boolean
下面看看可以把哪些类型对象的值复制给a
:
a = {b:1}
a = {b:1,c:undefined}
a = {b:1,c:'d'}
a = {b:1,10:true}
a = {b:1,10:true,20:false}
a = {10:true} //Error
a = {b:1,33:"red"} // Error
索引签名: [key:T]:U
句法成为索引签名,我们通过这种方式告诉TypeScript指定的对象可能有更多的键.索引签名还有一条规则要记住:键的类型(T
)必须可复制给number
或string
声明对象类型时,可选符号(?
)不是唯一的可用修饰符.此外,还可以使用readonly
修饰符把字段标记为只读:
let user:{ readonly firstName:string} = {firstName: 'abbey'}
user.firstName = 'abbey with an e' // Error
字面量对象表示法有一个特例:空对象类型({}
).除了null
和undefined
之外的任何类型都可以赋值给空对象类型,使用起来比较复杂.请尽量避免使用空对象类型:
let danger:{}
danger = {}
danger = {x:1}
danger = []
danger = 2
最后,还要讲一种对象类型的方式:Object
.这与{}
的作用基本一致,最好也避免使用
综上所述,在TypeScript中声明对类型有四种方式:
- 对象字面量表示法,也称对象的结构.
- 空对象字面量表示法(
{}
).尽量避免使用 object
类型.如果需要一个对象,但对对象的字段没有要求,使用这种方式.Object
类型.尽量避免使用
类型别名、并集、交集
类型别名
type Age=number
type Person = {name:string ,age:Age}
与变量声明一样,同一类型也不能定义两次.
同样与let
和const
一样是,类型别名采用块作用域.每一块代码和每一个函数都有自己的作用域,内部的类型别名将遮盖外部的类型别名.
并集类型和交集类型
type Cat = {name:string,purrs:boolean}
type Dog = {name:string,barks:boolean,wag:boolean}
type CatOrDogOrBoth = Cat|Dog
type CatAndDog = Cat&Dog
赋值给CatOrDogOrBoth
类型的变量,可以是Cat
类型的值,也可以是Dog
类型的值,还可以两者兼备.
// Cat
let a2: CatOrDogOrBoth = {
name: "Bonkers",
purrs: true
};
// Dog
a2 = {
name : "Domino",
barks : true,
wag : true,
};
// Both
a2 = {
name: "Donkers",
barks: true,
wag: true,
purrs:true,
}
一个并集类型(|
)的值不一定属于并集中的某一个成员,还可以同时属于每个成员.(并集相交时,即具有相同的字段)
交集类型拥有所有的字段
let b2: CatAndDog = {
name:"Domino",
purrs: true,
barks: true,
wag :true,
}
数组
let a:string[] = []
let g = []
g
比较特殊,在初始化空数组时,TypeScript不知道数组中元素的类型,推导出的类型为any
.向数组中添加元素后,TypeScript开始拼凑数组的类型.当数组离开定义时所在的作用域后,TypeScript将最终确定一个类型,不再扩张.
function buildArray()
{
let a =[] // any[]
a.push(1) // number[]
a.push('x') // (string|number)[]
return a
}
let myArray = buildArray() // (string|number)[]
myArray.push(true) // Error
元组
元组是数组的子类型,是定义数组的一种特殊方式,长度固定,各索引位上的值具有固定的已知类型.与其他多数类型不同,声明元组时必须显示注解类型.这是因为,创建元组使用的句法与数组相同(都使用方括号),而TypeScript遇到方括号推导出来的是数组类型
let a:[number] = [1]
let b:[string,string,number]=['malcolm','gladwell',1963]
元组也支持可选元素
let f:[number,number?] = [3]
let g:[number,number?] = [3,4]
元组也支持剩余元素
let friends:[string,...string[]]=['sara','tali','chloe','claire']
let list:[number,boolean,...string[]]=[1,false,'a','b','c']
只读数组和元组
TypeScript原生支持只读素组类型,用于创建不可变的数组.只读数组与常规数组没有多大的区别,只是不能就地更改.只能对只读数组使用不可变方法
let al: readonly number[] = [1, 2, 3, 4];
let al1 = al.concat(5);
let al2:ReadonlyArray<number> = al.concat(5);
al.push(6) // Error
null、undefined、void
和never
在JavaScript中有两个值表示缺少什么:null
和undefined
.TypeScript也支持这两个值,并且有各自的类型.在TypeScript中,undefined
类型只有undefined
一个值,null
类型也只有null
一个值.
往往不用区分二者,但是它们在语义上有细微的区别:undefined
的意思是尚未定义,而null
表示缺少值(例如在计算一个值的过程中遇到了错误),这只是一种约定.
除了null
和undefined
之外,TypeScript还有void
和never
类型.这两个类型有明确的特殊作用,进一步划分不同情况下的’不存在’:void
是函数没有显示返回任何值时的返回值,而never
是函数根本不返回(例如函数抛出异常或永远运行下去)时使用的类型.
如果说unknown
是其他每个类型的父类型,那么never
就是其他每个类型的子类型.我们可以把never
理解为’兜底类型’.意味着never
类型可以赋值给其他任何类型,在任何地方都能放心使用never
类型的值.这一点基本上只有理论意义.
枚举
enum Language
{
English,
Spaish,
Russian
}
let e1 = Language.Russian
let e2 = Language['English']
//枚举合并
enum Language2
{
English,
Spaish,
}
enum Language2
{
Chinese =2,
}
// 枚举的安全子集,const enum 不允许反向查找.默认也不会生成js代码,如果想为const enum生成运行时代码,需要把preserveConstEnums设为true
const enum Language3
{
English,
Spaish,
}
Typescript类型别名
1. 基本语法
- 为了避免重复工作,TypeScript提供了类型别名特性,允许为自定义类型组合分配一个名称
1.1. 示例
enum City { London = "LON", Paris = "PAR", Chicago = "CHI" }
type comboType = [string, number | true, 1 | 2 | 3 | City.London][];