Typescript | 淺談對于選項options的處理方案

問題情景:

最近為一個年代久遠的庫重寫了typescript版本,(這個庫能把html文本轉化為docx文檔)活合,里面遇到最主要的就是options的處理,也就是函數(shù)參數(shù)選項處理胧谈,情景如下:

const data = await asBlob(htmlString, { orientation: 'landscape', margins: { top: 100 } })

這里的函數(shù)入口的主選項允許只提供部分參數(shù),而且嵌套子選項的margins也需要允許只提供部分參數(shù)荸频。
剛開始我使用函數(shù)的可選和默認參數(shù)進行設計菱肖,可是效果不理想,想不出如何推導類型旭从。

處理方案:

后來我總結出了一套用PartialmergeOptions合并選項稳强,并且聲明子選項默認值,用默認值構造子選項類型的方法和悦。實現(xiàn)比較簡單和優(yōu)雅退疫,當然如果你有更好的解決方案,歡迎提出評論意見鸽素!

首先褒繁,我個人傾向于在最里層的函數(shù),也就是使用到這個參數(shù)的函數(shù)那里定義所需的數(shù)據(jù)類型馍忽。
比如margins是在 src/template/documentTemplates.ts 這里用到的棒坏,我們就在這個文件這里聲明Margins類型或者接口。
同時遭笋,我建議選項類型坝冕,先定義默認參數(shù),再用typeof進行初始化:

// 聲明margins的默認參數(shù)
export const defaultMargins = {
  top: 1440,
  right: 1440,
  bottom: 1440,
  left: 1440,
  header: 720,
  footer: 720,
  gutter: 0,
}
// 通過參數(shù)聲明margins類型
export type Margins = typeof defaultMargins
// 同文件函數(shù)直接引用這個類型
export const documentTemplate = (..., margins: Margins) => {}

但是坐梯,我們希望選項在入口函數(shù)的時候我們只需要填寫部分參數(shù)即可徽诲,比如上面的margins,我們可能只是想要指定top參數(shù)吵血,這該怎么處理呢谎替?
這里我建議在入口函數(shù)的相關參數(shù)處使用Partial部分類型。Partial是typescript全局提供的工具類型蹋辅,你只需要提供一個“完整類型”钱贯,它就能生成一個“部分類型”。

function asBlob(html: string, options: Partial<DocumentOptions> = {}) 

它的實現(xiàn)也十分簡單:

type Partial<T> = {
    [P in keyof T]?: T[P];
};

最后侦另,我們在入口函數(shù)向參數(shù)使用函數(shù)傳參處使用mergeOptions合并參數(shù)就可以了:

function mergeOptions<T>(options: T, patch: Partial<T>) {
  return { ...options, ...patch } as T
}
const marginsOptions = mergeOptions(defaultMargins, margins)

這一套方案可以消滅大多數(shù)的用嵌套對象做選項參數(shù)的情景啦秩命。

字面量自動擴展(type widen)問題

在項目中,我需要用一個字符串字面量(String Literal Types)來做參數(shù)褒傅,在正常使用的時候沒問題弃锐,比如:

function asBlob(html, {orientation: ''}) //編輯器會自動補全,并且類型正確推導

但是殿托,當把選項聲明為獨立的Object霹菊,再放進去的時候會提示TypeError,顯示oritentation應該是Orient類型支竹,不應該是string類型旋廷。

import { asBlob } from 'html-docx-js-typescript'
const opt = {
  margin: {
    top: 100
  },
  orientation: 'landscape' // type error: because typescript automatically widen this type to 'string' but not 'Orient' - 'string literal type'
}
await asBlob(html, opt)

這是怎么回事鸠按?我明明聲明的時候用的是字面量中的其中一個啊饶碘!
后來通過typescript issueSyntax for hinting literal type inference #10195了解到目尖,這是字面量參數(shù)自動發(fā)生了類型擴展(type widening),因為你聲明一個獨立對象的時候扎运,你不能保證這個字面量參數(shù)不會發(fā)生變化瑟曲,因此typescript自動把它擴展為string類型,導致類型錯誤绪囱!
這個時候我們應該讓它避免類型擴展测蹲,你可以暴露Orient 類型,用類型斷言來指定這個類型鬼吵,也可以用const把類型固定為常量扣甲。因為我不想暴露這個類型,讓用戶產(chǎn)生心智負擔齿椅,所以我推薦直接用as const琉挖。

const opt = {
  margin: {
    top: 100
  },
  orientation: 'landscape' as const
}

??如果有大佬提出更好的解決方案,可以評論區(qū)交流哈~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末涣脚,一起剝皮案震驚了整個濱河市示辈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌遣蚀,老刑警劉巖矾麻,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異芭梯,居然都是意外死亡险耀,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門玖喘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甩牺,“玉大人,你說我怎么就攤上這事累奈”崤桑” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵澎媒,是天一觀的道長搞乏。 經(jīng)常有香客問我,道長戒努,這世上最難降的妖魔是什么查描? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上冬三,老公的妹妹穿的比我還像新娘。我一直安慰自己缘缚,他們只是感情好勾笆,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著桥滨,像睡著了一般窝爪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上齐媒,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天蒲每,我揣著相機與錄音,去河邊找鬼喻括。 笑死邀杏,一個胖子當著我的面吹牛,可吹牛的內容都是我干的唬血。 我是一名探鬼主播望蜡,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拷恨!你這毒婦竟也來了脖律?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤腕侄,失蹤者是張志新(化名)和其女友劉穎小泉,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冕杠,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡微姊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拌汇。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柒桑。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖噪舀,靈堂內的尸體忽然破棺而出魁淳,到底是詐尸還是另有隱情,我是刑警寧澤与倡,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布界逛,位于F島的核電站,受9級特大地震影響纺座,放射性物質發(fā)生泄漏息拜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望少欺。 院中可真熱鬧喳瓣,春花似錦、人聲如沸赞别。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仿滔。三九已至惠毁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間崎页,已是汗流浹背鞠绰。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留飒焦,地道東北人蜈膨。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像荒给,于是被迫代替她去往敵國和親丈挟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內容