0%

【047】typescript:对象类型

对象是包含一组键值对的实例。值可以是标量、函数、数组、对象等。

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ts
let obj = {
a: 'obj', // 标量
b: () => {}, // 函数
c: [1, 2, ,3], // 数组
d: { key01: 'a', key02: 'b' } // 对象
}
console.log(obj.a) // obj
console.log(obj.b()) // 我是函数
console.log(obj.c) // [1, 2, 3]
console.log(obj.d) // { key01: 'a', key02: 'b' }

// 编译成js后
var obj = {
a: 'obj', // 标量
b: function () { return '我是函数'; }, // 函数
c: [1, 2, 3], // 数组
d: { key01: 'a', key02: 'b' } // 对象
};
console.log(obj.a);
console.log(obj.b());
console.log(obj.c);
console.log(obj.d);

定义对象类型

匿名对象变量

匿名对象是在定义变量时直接使用花括号{},来定义一个对象类型。

1
const person: { name: string, age: number } = { name: '老王', age: 30 }

匿名对象函数

1
2
3
4
const personFn = (person: { name: string, age: number }) => {
console.log(`姓名:${person.name},年龄:${person.age}`)
}
personFn({ name: '老王', age: 30 }) // 姓名:老王,年龄:30

接口类型

从上面的例子可以看出,每次都这样写对象类型会很麻烦,如果遇到使用同一种对象类型的数据时,需要多次写入,增添了工作量。那么这个时候就可以使用接口来定义对象类型,使代码更加可读、易于维护。

1
2
3
4
5
6
7
8
9
interface Person {
name: string,
age?: number
}
const personFn = (person: Person) => {
if (person.age !== undefined) console.log(`姓名:${person.name},年龄:${person.age}`)
else console.log(`姓名:${person.name}`)
}
personFn({ name: '老王' }) // 姓名:老王

类型别名

类型别名用来给一个类型起个新名字,使用 type 创建类型别名,类型别名不仅可以用来表示基本类型,还可以用来表示对象类型、联合类型、元组和交集。

1
2
3
4
5
6
7
8
9
type Person = {
name: string,
age? : number
}
const personFn = (person: Person) => {
if (person.age !== undefined) console.log(`姓名:${person.name},年龄:${person.age}`)
else console.log(`姓名:${person.name}`)
}
personFn({ name: '老王' }) // 姓名:老王

属性修饰符

可选属性

对象类型还可以指定它们的部分或全部属性是可选的。为此,请在属性名称后添加 ?

比如我们在填写个人信息时,年龄一般会选择不填写。

1
2
3
4
const personFn = (person: { name: string, age?: number }) => {
console.log(`姓名:${person.name},年龄:${person.age}`)
}
personFn({ name: '老王' }) // 姓名:老王,年龄:undefined

从上面例子的结果可以看出,如果访问了一个不存在的属性age并不会运行错误,而是会返回undefined,所以当我们在读取可选属性中的数据时,尽量在使用这个属性之前检查一下,如下:

1
2
3
4
5
const personFn = (person: { name: string, age?: number }) => {
if (person.age !== undefined) console.log(`姓名:${person.name},年龄:${person.age}`)
else console.log(`姓名:${person.name}`)
}
personFn({ name: '老王' }) // 姓名:老王

只读属性

我们使用 readonly 关键字来声明只读属性,属性的值一旦被赋值就不能再次修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
type Person = {
name: string,
readonly age: number,
readonly sex: string
}
const person: Person = {
name: '老王',
age: 30,
sex: '男'
}
person.name = '翠花'
person.age = 18 // 报错,只读属性一旦被赋值就不能再次修改
person.sex = '女' // 报错,只读属性一旦被赋值就不能再次修改

索引签名

有时你无法提前知道类型属性的所有名称,在这种情况下,你可以使用索引签名来描述可能值的类型。

  1. 基本用法

    1
    2
    3
    4
    5
    6
    7
    8
    interface personInfo {
    [key: string]: string | number
    }
    const person_info: personInfo = {
    name: '老王',
    sex: '男'
    }
    console.log(person_info) // { name: '老王', sex: '男' }
  2. 只读索引签名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    interface personInfo {
    readonly [key: string]: string | number
    }
    const person_info: personInfo = {
    name: '老王',
    age: 30,
    sex: '男'
    }
    person_info.age = 18 // 报错
  3. 联合类型索引签名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    interface personInfo {
    [key: string]: string | number
    }
    const person_info: personInfo = {
    name: '老王',
    age: 30,
    sex: '男'
    }
    console.log(person_info) // { name: '老王', age: 30, sex: '男' }

泛型对象类型

在我们还不知道是什么样子的对象类型时,可以使用 泛型 先占位,等知道后再补充。

1
2
3
4
5
6
7
8
9
10
11
interface Person<T> {
phone: T
}
const person01: Person<number> = {
phone: 13222222222
}
const person02: Person<string> = {
phone: '020-1111111'
}
console.log(person01) // { phone: 13222222222 }
console.log(person02) // { phone: '020-1111111' }