[答案公布] TypeScript 每日挑战:约束多个函数参数间的类型关系

1,299 阅读2分钟

「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!

其实大多数 TypeScript 开发者,对 TypeScript 的利用,还停留在初级水平。

第 1 期的 TypeScript 每日挑战给大家出了这样的一道题目,恭喜交流群中的 @子非鱼 @jonas 做出了高分答案。

先来回顾一下题目:

题目

// 我有一堆必填字段
interface DocType {
    aaa: string,
    bbb: string,
    ccc: string
}

// 函数类型定义,等你来改写 ...
function makeDoc(part1: any, part2: any) {
    // ...
}

有一个名为 DocTypeinterface,包含一组必填字段

需要实现一个名为 makeDoc 的函数定义,它有 2 个参数:part1part2,它们都拥有 DocType 的部分字段(Partial<DocType>

需要你在 TypeScript 类型定义层面,实现 makeDoc 两个参数的类型校验:

  1. part1part2 的字段合并后,即 Object.assign({}, part1, part2),满足 DocType 的类型定义。
  2. part1part2 中不能有重复字段。

测试用例如下:

// 合法
makeDoc({ aaa: '111', bbb: '222' }, { ccc: '333' })

// 合法
makeDoc({ aaa: '111', bbb: '222', ccc: '333' }, {})

// 合法
makeDoc({ccc: '333'}, { aaa: '111', bbb: '222'
})

// 应该报错(因为缺少必填字段 ccc)
makeDoc({ aaa: '111' }, { bbb: '222' })

// 应该报错(因为 aaa 字段重复出现)
makeDoc({ aaa: '111', bbb: '222' }, { aaa: '333', ccc: '444' })

答案公布

本题目的难点主要有几个:

  1. 函数参数类型不定,需要使用泛型进行类型推测
  2. 在多个函数参数之间类型的互相约束

要解决本题目,你需要了解的 TypeScript 技能点:

  1. 泛型:www.typescriptlang.org/docs/handbo…
  2. Mapped Types: www.typescriptlang.org/docs/handbo…
  3. 类型转换实用工具:www.typescriptlang.org/docs/handbo…

解决思路就是:

  1. 利用泛型推测参数 part1 的类型
  2. 利用 part1 的类型,去约束 part2 的类型

方式一

通过 泛型 + Mapped Type 解决:

function makeDoc<T extends keyof DocType>(part1: {
    [K in T]: DocType[K]
}, part2: {
    [K in Exclude<keyof DocType, T>]: DocType[K]
}) {
    // ...
}

方式二

通过 泛型 + Partial + Omit 解决:

function makeDoc<T extends Partial<DocType>>(part1: T, part2: Omit<DocType, keyof T>) {
    // ...
}

是不是感觉 TypeScript 的水有深了一丢丢? 关注 [TypeScript全栈开发],每周一个 TypeScript 高阶挑战等着你!

(正文完)


如果你对使用 TypeScript 进行全栈开发感兴趣,欢迎关注目前世界上唯一支持 TypeScript 复杂类型运行时自动检测和二进制序列化的TypeScript 开源 RPC 框架 —— TSRPC

GitHub:github.com/k8w/tsrpc
中文文档:tsrpc.cn
视频教程:www.bilibili.com/video/BV1hM…