如何将现有TypeScript类型的字段作为函数参数类型?
问题
假设定义了如下类型:
type Book = { title: string pages: Page[] }
出于历史原因,需要一个名为readBook的函数,接收Book类型的字段作为独立参数(而非Book对象本身),希望无需手动重复定义字段类型来正确标注函数参数。尝试过以下写法但都不符合需求:
function readBook(title: string, pages: Page[]) { ... } // 可用但需手动重复类型 function readBook(book: Book) { ... } // 接收对象,不符合需求 function readBook(...args: Book) { ... } // 语法错误,args需为数组类型 function readBook(...Book) { ... } // 语法错误
期望实现类似如下的写法(直接基于Book类型生成参数):
function readBook(...Book) { console.log(title) pages.map(page => readPage(page)) }
请问是否有可行的实现方式或近似方案?
解决方案
方法一:元组参数解构(推荐)
通过提取Book的字段类型构建元组,再用解构直接获取命名参数,既避免重复定义类型,又能保持和Book类型的关联:
type Book = { title: string pages: Page[] } // 同步Book的字段类型为参数元组,顺序和Book属性一致 type BookArgs = [title: Book['title'], pages: Book['pages']] function readBook(...[title, pages]: BookArgs) { console.log(title); pages.map(page => readPage(page)); }
后续Book类型更新时,BookArgs会自动同步,完全满足需求。
方法二:自动转换对象为元组(注意属性顺序)
使用工具类型自动将Book对象类型转为元组参数,但要注意TypeScript 4.0及以上版本才保证对象属性顺序稳定:
type Book = { title: string pages: Page[] } // 工具类型:将对象类型转换为对应属性值的元组 type ObjectToTuple<T> = { [K in keyof T]: T[K] } extends ArrayLike<infer U> ? U[] : never function readBook(...[title, pages]: ObjectToTuple<Book>) { console.log(title); pages.map(page => readPage(page)); }
这种方式无需手动维护元组的字段顺序,但要确保Book的属性顺序和你期望的参数顺序一致。
备选方案:对象解构参数
如果历史代码可以调整调用方式,可直接解构Book对象参数,调用时用展开语法适配:
function readBook({ title, pages }: Book) { console.log(title); pages.map(page => readPage(page)); } // 调用示例: readBook({ title: "TypeScript Guide", pages: [] }); // 从已有Book对象展开: const myBook: Book = { title: "...", pages: [] }; readBook({ ...myBook });
但这种方法本质是接收对象参数,若历史代码必须传两个独立参数,还是前两种方法更贴合需求。
内容的提问来源于stack exchange,提问作者jyurek
相关产品推荐
相关产品推荐

