对象接口, 对象对接的好处是可以明确对象的类型,避免一些边界问题。
下面我们来看一个例子。
interface List {
id: number;
name: string;
}
interface Result {
data: List[]
}
function render(result: Result) {
result.data.forEach((value) => {
console.log(value.id, value.name)
})
}
let result = {
data: [
{id: 1, name: 'A'},
{id: 2, name: 'B'}
]
}
render(result);
这里的LIst就定义好了这个对象类型属性。在实际开发过程中,后端会传过来预定之外的字段, 比如后端传入的data多了sex字段。
比如下面的例子, result多了sex属性。这个时候我们常用的做法是类型断言。
interface List {
id: number;
name: string;
}
interface Result {
data: List[]
}
function render(result: Result) {
result.data.forEach((value) => {
console.log(value.id, value.name)
})
}
let result = {
data: [
{id: 1, name: 'A', sex: 'male'},
{id: 2, name: 'B'}
]
}
render(result);
类型断言
类型断言是告诉编译器绕过这种检查。所以类型断言更像是类型的选择,而不是类型转换。
类型断言的方法
使用类型断言有两种方法:
<类型>值
// 或者
值 as 类型
as 方法
interface List {
id: number;
name: string;
}
interface Result {
data: List[]
}
function render(result: Result) {
result.data.forEach((value) => {
console.log(value.id, value.name)
})
}
let result = {
data: [
{id: 1, name: 'A', sex: 'male'},
{id: 2, name: 'B'}
]
}
render(result as Result);
<类型>值
推荐以 as 方式,因为 jsx 这样的语法中只支持 as 方式。
interface List {
id: number;
name: string;
}
interface Result {
data: List[]
}
function render(result: Result) {
result.data.forEach((value) => {
console.log(value.id, value.name)
})
}
let result = {
data: [
{id: 1, name: 'A', sex: 'male'},
{id: 2, name: 'B'}
]
}
render(<Result>result);
可选属性,只读属性
可选属性
接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 例如给函数传入的参数对象中只有部分属性赋值了。带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号。
只读属性
顾名思义就是这个属性是不可写的,对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly来指定只读属性。 只读属性是不可以修改的。
interface List {
readonly id: number; // 这里是只读属性
name: string;
age?: number; // 这里是可选属性
}
interface Result {
data: List[]
}
function render(result: Result) {
result.data.forEach((value) => {
console.log(value.id, value.name)
})
}
let result = {
data: [
{id: 1, name: 'A', sex: 'male'},
{id: 2, name: 'B'}
]
}
render(<Result>result);
可索引类型
可索引类型的作用
我们先来看一个例子。
nterface List {
color?: string;
width: number;
}
function createList(config: List) {
console.log(config.color);
}
let myList = createList({colour: 'red', width: 100});
这里会编译失败。Argument of type '{ colour: string; width: number; }' is not assignable to parameter of type 'List'.
绕过上面的检查,可以采用上面的类型断言,
let myList = createList({colour: 'red', width: 100} as List);
然而,最佳的方式是能够添加一个字符串索引签名,前提是你能够确定这个对象可能具有某些做为特殊用途使用的额外属性。
interface List {
color?: string;
width: number;
[propName: string]: any; // 返回值是any,如果是确定值,那么注意color和width的返回值类型必须是这个确定值的子集
}
function createList(config: List) {
console.log(config.color);
}
let myList = createList({colour: 'red', width: 100});
索引签名类型
TypeScript支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用 number来索引时,JavaScript会将它转换成string然后再去索引对象。 也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引,因此两者需要保持一致。
class Animal {
name: string;
}
class Dog extends Animal {
breed: string;
}
// 错误:使用数值型的字符串索引,有时会得到完全不同的Animal!
interface NotOkay {
[x: number]: Animal;
[x: string]: Dog;
}
//编译OK
interface Okay {
[x: number]: Dog; //Dog是Animal子类
[x: string]: Animal;
}
|
请发表评论