交叉类型 &
有类型A的特性,也有类型B的特性
/* 交叉类型 */
interface Mother {
name: string
hug(): void
}
interface Teacher {
name: string
teach(): void
}
type MotherAndTeacher = Mother & Teacher
// mt 则同时拥有了hug和teach的方法
let mt: MotherAndTeacher
mt.hug()
mt.teach()
答案
解析
交叉类型是将多个类型合并为一个类型。这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。
所以函数 getAnimalInfo 的形参 animal 的类型为 Panda & Koala 即
{ name: string; food: string; age: number; }
题目比较简单,答案为 bamboo,12。
ts 中的 typeof
/* ts 中的 typeof */
// 这是原场景,有很多冗余部分,比如修改类型结构无需维护多套
type People_5301 = {
name: string
age: number
}
let mmo_5301: People_5301 = {
name: 'a',
age: 18
}
function printName(p: People_5301) {
console.log(p.name)
}
// 使用typeof关键字,只需要维护一套
let mmo_5302 = {
name: 'a',
age: 18,
gender: 'm'
}
type People_5302 = typeof mmo_5302
function printName(p: People_5302) { // 该类型则 = mmo_5302
console.log(p.name)
}
答案
解析
animal 的类型为 typeof panda 即
{ name: string; age: number; }
题目比较简单,答案为正确。
索引访问操作符
/* 索引访问操作符 */
interface People_5303 {
name: string
age: number
job: {
name: string
type: string
}
hobbies:{
name: string,
timesPerWeek: number
}[]
}
// 取People_5303的job结构
let mmo_5303: People_5303['job'] = {
name: 'a',
type: 'teacher'
}
// 第二种索引方式,取数组结构内的某一属性,此处无需考虑取的下标是第几个,因为都是一样的
let swimTimesPerWeek: People_5303['hobbies'][0]['timesPerWeek'] = 3
答案
解析
使用 Animal.info.name 来声明函数 getAnimalName 的返回值类型是错误的。
无法访问 Animal.info,因为 Animal 是类型,不是命名空间。
正确的表示方式为
Animal[‘info’][‘name’]
keyof 索引类型查询操作符
/* keyof 索引类型查询操作符 */
interface People_5304 {
name: string
age: number
gender: 'male' | 'female'
}
type PeopleKey_5304 = 'name' | 'age' | 'gender' //常见写法
type PeopleKey_5305 = keyof People_5304 // 使用keyof关键字,效果等同于上面
function getPeopleValueByKey(p: People_5304, key: PeopleKey_5305) {
return p[key]
}
答案
解析
keyof 为索引类型查询操作符。
keyof T 的结果为 T 上已知的公共属性名的联合。
变量 panda 的类型为 typeof Animal 即
“name” | “age”
所以正确答案为 C。
映射类型 in
/* 映射类型 */
interface People_5306 {
name: string
age: number
gender: 'male' | 'female'
}
type PeopleKey_5306 = 'name' | 'age' | 'gender'
type PartialPeople_5306 = {
[K in PeopleKey_5306]?: People_5306[K] // 使用in操作符,将PeopleKey的每一项作为可选项
}
// 报错,缺少age、gender
let mmo_5306: People_5306 = {
name: 'mmo'
}
// 正确, 每一项都是可选项
let aab_5306: PartialPeople_5306 = {
name: 'mmo'
}
// 去除掉PeopleKey,最终可简写为
type PartialPeople_5307 = {
[K in keyof People_5306]?: People_5306[K]
}
// 另一种泛型写法, 用于将任何类型T都转化为可选类型T
type Part<T> = {
[K in keyof T]?: T[K]
}
let ccd:Part<People_5306> = { // 泛型使用方式,实现同样的效果
name: 'mmo'
}
答案
解析
接口 Animal 的类型为
{ name: string; age: number; }
Option
{ name?: string; age?: number; }
所以语法是正确的。
条件类型
/* 条件类型 */
type Beef = { beefWight: number }
type Fish = { fishWight: number }
type Lamb = { lambWight: number }
type StoneBaked<T> = T & {
stoneTemperature: number
}
type FireBaked<T> = T & {
fireTemperature: number
}
// 如果 传入的是Beef,则使用的是StoneBaked...
type Baked<T> =
T extends Beef ? StoneBaked<T> :
T extends Fish ? FireBaked<T> :
StoneBaked<T>
// 每个声明都拥有自己的方法
let b: Baked<Beef>
let f: Baked<Fish>
let l: Baked<Lamb>
答案
解析
类型 Condition 的条件判断流程。简单如下
Condition(`接收一个类型 T`) {
if (`T 包含 Panda 的结构类型`) {
return `number`;
} else {
if (`T 包含 Koala 的结构类型`) {
return `string`;
} else {
return `any`;
}
}
}
所以 Condition