你可以在 Typescript 函数中有可选的解构参数吗?

Posted

技术标签:

【中文标题】你可以在 Typescript 函数中有可选的解构参数吗?【英文标题】:Can you have optional destructured arguments in a Typescript function? 【发布时间】:2019-03-21 10:38:02 【问题描述】:

我想编写一个函数,它接受一个对象参数,在函数签名中使用解构,并且该参数是可选的:

myFunction(opt1, opt2?: opt1?: boolean, opt2?: boolean)

但是,Typescript 不允许(“绑定模式参数在实现签名中不能是可选的。”)。

不解构当然可以:

myFunction(options?: opt1?: boolean, opt2?: boolean) 
  const opt1 = options.opt1;
  const opt2 = options.opt1;
  ...

好像这些应该是一样的,但是上面的例子是不允许的。

我想使用一种解构语法 (1) 因为它存在,而且是一种很好的语法,而且上面的两个函数的行为应该是一样的,并且 (2) 因为我也想要一种简洁的方式指定默认值:

myFunction(opt1, opt2 = true?: opt1?: boolean, opt2?: boolean)

如果不进行解构,我必须将这些默认值隐藏在函数的实现中,或者有一个实际上是带有构造函数的某个类的参数......

【问题讨论】:

【参考方案1】:

改用默认参数:

function myFunction( opt1, opt2 = true :  opt1?: boolean; opt2?: boolean;  = ) 
    console.log(opt2);


myFunction(); // outputs: true

为了不破坏undefined是必要的:

function myFunction( opt1, opt2 ) 

    
// Uncaught TypeError: Cannot destructure property `opt1` of 'undefined' or 'null'.
myFunction();

【讨论】:

有没有办法避免参数对象中opt1opt2 的重复?类似function myFunction( opt1?: boolean; opt2?: boolean = false; = ) @icl7126 不幸的是没有。通常在这些情况下我会将内联类型提取到接口中,因为它太冗长了:( ...和there's no easy way to define default interface property values。【参考方案2】:

如果没有作为参数给出的对象,则不能解构。因此,如前一篇文章所述,在 parmas 中使用默认对象:

type Options =  opt1?: boolean; opt2?: boolean; 

function myFunction( opt1, opt2 : Options = ) 
    console.log(opt2, opt1);


myFunction() // undefined,  undefined 
myFunction(opt1: false); // undefined,  false 
myFunction(opt2: true); // true,  undefined

我想补充的是,当满足以下 2 个条件时,参数中的这种解构模式会增加最大的价值:

选项的数量可能会发生变化 函数的 API 可能会发生变化。即函数参数可能会改变

基本上解构为您提供了更大的灵活性,因为您可以添加任意数量的选项,而只需对函数的 API 进行最少的更改。

但是,更基本的版本会更简单:

// If the function is not likely to change often just keep it basic:
function myFunctionBasic( opt1? :boolean, opt2?: boolean ) 
    console.log(opt2, opt1);

【讨论】:

这个答案是唯一为我解决问题的答案(使用函数重载)【参考方案3】:

如果您想混合可选参数和必需参数但有一个所有值都是必需/非空的导出类型,这是最好的方法:

export function newCar(args: 
    year?: number
    make?: string
    model: string
    owner: [string, string]
) 
    const defaults = 
        year: 1999,
        make: "toyota",
    
    return  ...defaults, ...args 
    // to get a Readonly<Car>:
    // return Object.freeze(args)


export type Car = ReturnType<typeof newCar>

const c = newCar( model: "corolla", owner: ["Gorg", "Blafson"] )

export function print(c: Car) 
    console.log(`$c.owner's gorgeous $c.year $c.model from $c.make`)

【讨论】:

以上是关于你可以在 Typescript 函数中有可选的解构参数吗?的主要内容,如果未能解决你的问题,请参考以下文章

angularjs 路由可以有可选的参数值吗?

15TypeScript-函数

mongoose - 有可选的附加隐式字段

TypeScript面试题

发布 TypeScript 包时如何处理可选的对等依赖项?

C main 函数是可选的吗?你可以在它之外编写代码吗?