TypeScript对象类型
针对对象的部分,做了如下的回顾
对象属性的三种描述方法:
- 通过对象本身的key value
- 通过接口
- 通过类型别名
属性修饰符
对象中的属性可以指定如下几件事:
- 是否可选
- 是否只读
- 属于什么类型
可选修饰符 ?
通过?
修饰符表示属性可选。
当开启strictNullChecks
时,会提示潜在的错误
1 | function paintShape(opts: PaintOptions) { |
解决undefined
的问题,有两种方法
- 手动判断是否为
undefined
- 赋默认值(通过解构函数参数赋默认值)
注意,目前没有办法在解构模式中放置类型注释。因为在 JavaScript 中,下面的语法代表的意思完全不同
1 | function draw({ shape: Shape, xPos: number = 100 /*...*/ }) { |
在对象解构语法中,shape: Shape 表示的是把 shape 的值赋值给局部变量 Shape。 xPos: number 也是一样,会基于 xPos 创建一个名为 number 的变量。
只读修饰符 readonly
对于使用readonly
的属性,在运行时不会影响任何行为,但在类型检查时不允许写入readonly
仅表示属性本身不能重新写入,并不等于完全不会发生改变(可以对比const声明的对象理解)
TypeScript 在检查两个类型是否兼容的时候,并不会考虑两个类型里的属性是否是 readonly,这就意味着,readonly 的值是可以通过别名修改的
1 | interface Person { |
索引签名
适用于不知道key值,但知道key值的类型
1 | interface StringArray { |
这个索引签名表示当一个 StringArray 类型的值使用 number 类型的值进行索引的时候,会返回一个 string类型的值
一个索引签名的属性类型必须是 string 或者是 number
由于js会隐式的将数字索引转为字符串,所以数字索引返回的类型一定是字符串索引返回的子类型
1 | interface Animal { |
通过给索引签名设置只读属性,可以控制赋值行为
1 | interface ReadonlyStringArray { |
属性继承
通过extends
关键字继承接口interface A extends B
交叉类型
通过&
合并两个类型
接口继承与交叉类型
通过接口继承的方式去重写某个属性会报错,但是交叉类型不会报错。
1 | interface Colorful { |
虽然不会报错,那 color
属性的类型是什么呢,答案是 never
,取得是 string
和 number
的交集
泛型对象类型
可以理解为一种延迟指定的类型,只有在实例化时才会作为参数指明类型
1 | interface Box<Type> { |
可以通过泛型函数来避免函数的重载
1 | function setContents<Type>(box: Box<Type>, newContents: Type) { |
数组类型
类型 number[]
或者 string[]
只是 Array<number>
和 Array<string>
的简写形式而已
Array 本身就是一个泛型
1 | interface Array<Type> { |
ReadonlyArray 类型
是一个特殊类型,它可以描述数组不能被改变,主要是用来做意图声明。用于让使用者放心传入数组或禁止使用者更改数组
1 | function doStuff(values: ReadonlyArray<string>) { |
ReadonlyArray 并不是一个我们可以用的构造器函数,但可以直接把一个常规数组赋值给 ReadonlyArray
TypeScript 也针对 ReadonlyArray<Type>
提供了更简短的写法 readonly Type[]
1 | function doStuff(values: readonly string[]) { |
Arrays 和 ReadonlyArray 并不能互相赋值
元组类型
是另外一种 Array 类型。适用于元素个数和类型已知。type StringNumberPair = [string, number];
- 可以解构元组
1
2
3
4
5function doSomething(stringHash: [string, number]) {
const [inputString, hash] = stringHash;
console.log(inputString); // const inputString: string
console.log(hash); // const hash: number
} - 可选属性会影响类型的length
- 可以使用剩余元素语法,但必须是array或tuple(元组)类型
有剩余元素的元组并不会设置 length - 可选元素和剩余元素可以使ts在参数列表里使用元组
1
2
3
4function readButtonInput(...args: [string, number, ...boolean[]]) {
const [name, version, ...input] = args;
// ...
}
readonly 元组类型(readonly Tuple Types)
元组类型也是可以设置 readonly
,TypeScript 不会允许写入 readonly
元组的任何属性
1 | function doSomething(pair: readonly [string, number]) { |
在大部分的代码中,元组只是被创建,使用完后也不会被修改,所以尽可能的将元组设置为 readonly 是一个好习惯
如果我们给一个数组字面量 const 断言,也会被推断为 readonly 元组类型
1 | let point = [3, 4] as const; |
尽管 distanceFromOrigin 并没有更改传入的元素,但函数希望传入一个可变元组。因为 point 的类型被推断为 readonly [3, 4],它跟 [number number] 并不兼容,所以 TypeScript 给了一个报错。
TypeScript对象类型