別這么用 TypeScript 類型!試試 Map 模式吧
介绍
在实际项目中工作时,我遇到了一个特别的TypeScript实现,它是功能性的但不够灵活。在这篇文章里,我将讲述我遇到的问题,以及我如何通过使用Map模式使设计更加灵活。 我碰到了这种 TypeScript 类型定义。 此外,还定义了这种 它就是这样被用在一个函数里。 现在,想象一下开发者需要添加一个新的反应,比如爱心或鼓掌。鉴于当前的设置,他们需要做以下几件事: 更新后端代码,以处理新的反应类型。 所以他们不是只在一个地方添加新的反应,而是结果在三个或更多的文件中进行修改,这增加了错误和冗余的可能性。这种方法耦合得很紧。 我通过引入一个更灵活和可重用的结构,想出更简洁的解决方案。 无具体内容需要解释。 在 尽管新的解决方案提供了灵活性,但也引入了添加未经审核的反应的风险,这意味着任何人都可以随时可能添加任何字符串内容作为反应。我们肯定不希望看到这种情况。 为解决这个问题,我们可以更严格地控制允许反应。 这里是我们将反馈限制在一组允许值内的更新版本。 视觉表现 这种方法兼顾了灵活性和控制: 这段代码符合开闭原则(OCP),通过扩展来增加新功能,无需修改现有代码。 使用这种模式,我们可以轻松地扩展反应种类列表而不会修改太多文件,同时也能严格控制可以添加的新内容。 代码? 你可以在这里访问这个仓库[这里](https://github.com/perisicnikola37/dev-to-rater)\。 别的故事 ✨ 找我聊聊 GitHub (GitHub主页), LinkedIn (领英主页), dev.to (dev.to主页) 希望你今天学到点新东西!✌️ // FinalResponse.ts
import { Reaction } from './Reaction'
export type 最终响应 = {
总分: number
标题罚分: number
句子罚分: number
字符罚分: number
单词罚分: number
标题: string[]
句子: string[]
单词: string[]
链接: { href: string; text: string }[]
超出: {
超出句子: string[]
重复的单词: { 单词: string; 数量: number }[]
}
反应: {
likes: Reaction
unicorns: Reaction
explodingHeads: Reaction
raisedHands: Reaction
fire: Reaction
}
}Reaction(反应)类型。 // Reaction.ts
export type Reaction = {
count: number
percentage: number
}
这种方法的问题在于
// calculator.ts
export const calculateScore = (
headings: string[],
sentences: string[],
words: string[],
totalPostCharactersCount: number,
links: { href: string; text: string }[],
reactions: {
likes: Reaction,
unicorns: Reaction,
explodingHeads: Reaction,
raisedHands: Reaction,
fire: Reaction,
},
): FinalResponse => {
// 计算分数的逻辑...
}
FinalResponse.ts 文件以添加新的反应类型。Reaction.ts 类型。calculateScore 函数,使其包含新的反应。// 最终响应文件,定义了评分和惩罚规则
// FinalResponse.ts
import { Reaction } from './Reaction'
export type ReactionMap = Record<string, Reaction>
export type FinalResponse = {
totalScore: number,
headingsPenalty: number,
sentencesPenalty: number,
charactersPenalty: number,
wordsPenalty: number,
headings: string[],
sentences: string[],
words: string[],
links: { href: string; text: string }[],
exceeded: {
exceededSentences: string[],
repeatedWords: { word: string; count: number }[],
},
reactions: ReactionMap,
}
清洁代码
ReactionMap: 这种类型使用 Record<string, Reaction> 形式,表示任何字符串都可以作为键,而值的类型始终为 Reaction。FinalResponse: 现在,FinalResponse 中的 reactions 字段的类型为 ReactionMap,这意味着你可以根据需要动态添加任何反应而无需更改其他文件。calculator.ts 文件中,该函数现在是这样的:
瑞典有一说:但是等等!我们需要一点控制
// calculator.ts
export const calculateScore = (
headings: string[],
sentences: string[],
words: string[],
totalPostCharactersCount: number,
links: { href: string; text: string }[],
reactions: ReactionMap,
): FinalResponse => {
// 分数计算...
} // FinalResponse.ts
import { Reaction } from './Reaction'
type AllowedReactions =
| 'likes'
| 'unicorns'
| 'explodingHeads'
| 'raisedHands'
| 'fire'
export type ReactionMap = {
[key in AllowedReactions]: Reaction
}
export type FinalResponse = {
totalScore: number
headingsPenalty: number
sentencesPenalty: number
charactersPenalty: number
wordsPenalty: number
headings: string[]
sentences: string[]
words: string[]
links: { href: string; text: string }[]
exceeded: {
exceededSentences: string[]
repeatedWords: { word: string; count: number }[]
}
reactions: ReactionMap
}
AllowedReactions 类型轻松地添加新的反应。
共同學習,寫下你的評論
評論加載中...
作者其他優質文章


