为作为参数传递的TypeScript对象设置默认值


195
function sayName(params: {firstName: string; lastName?: string}) {
    params.lastName = params.lastName || 'smith';  // <<-- any better alternative to this?
    var name = params.firstName + params.lastName
    alert(name);
}

sayName({firstName: 'bob'});

我曾想过像这样的事情可能会起作用:

function sayName(params: {firstName: string; lastName: string = 'smith'}) {

显然,如果这些是简单的参数,则可以使用:

function sayName(firstName: string, lastName = 'smith') {
    var name = firstName + lastName;
    alert(name);
}

sayName('bob');

在coffeescript中,您可以访问条件存在运算符,因此可以执行以下操作:

param.lastName ?= 'smith'

哪个可以编译为javascript:

if (param.lastName == null) {
    param.lastName = 'smith';
}

您建议的解决方案params.lastName = params.lastName || 'smith';实际上还不错-它可以处理空字符串,未定义的字符串和空值。
Fenton 2014年

@SteveFenton和任何虚假的。对于姓氏来说很好,但是通常不是一个好主意。这就是Typescript将默认值转换为的原因if(typeof x === "undefined") { … }。并不是您不知道,而是指出了OP的一般情况。
IngoBürk'14

1
@IngoBürk是正确的,但是由于lastName?: string它只能像SteveFenton所说的那样“处理空字符串,未定义的字符串和空值”。
AJP

@AJP在Typescript中,是的。但这只是编译时间。无论哪种方式,就像我说的那样,只是指出了一个一般情况:)
IngoBürk2014年

2
在这里同意史蒂夫的观点。通常,最好有一个配置参数而不是10个参数。在这种情况下params.lastName = params.lastName || 'smith';,我使用的是模式
basarat 2014年

Answers:


210

实际上,现在似乎有一种简单的方法。以下代码可在TypeScript 1.5中使用:

function sayName({ first, last = 'Smith' }: {first: string; last?: string }): void {
  const name = first + ' ' + last;
  console.log(name);
}

sayName({ first: 'Bob' });

诀窍是首先将要从参数对象中选择的键放在方括号中,并key=value包含所有默认值。然后加上:和类型声明。

这与您尝试执行的操作稍有不同,因为params您没有拥有完整的对象,而是拥有了取消引用的变量。

如果要将传递给函数的内容设为可选,请?为类型中的所有键添加a,并={}在类型声明后添加默认值:

function sayName({first='Bob',last='Smith'}: {first?: string; last?: string}={}){
    var name = first + " " + last;
    alert(name);
}

sayName();

该解决方案提供了一种有意义的代码提示/智能功能,因为它显示出参数已完全解构。我不希望在示例中有多个参数的设置对象中看到该样式。
WiredPrairie 2015年

3
是否也可以重写此解决方案以使用类似“ sayNameSettings”的接口/类?
Stef Heyenrath

4
在这样做的同时,以这种方式破坏论点很难遵循IMO。
PW Kad

1
您可以使用'as'关键字(我认为它更具可读性),例如{first ='Bob',last ='Smith'}如{first ?: string; last ?: string},但理想情况下,您应该创建一个接口来处理这种情况……
Frohlich

1
有没有办法将options对象传递给另一个函数?
Dylanthepiguy

50

Typescript现在支持默认参数:

https://www.typescriptlang.org/docs/handbook/functions.html

另外,添加默认值可以省略类型声明,因为可以从默认值推断出它:

function sayName(firstName: string, lastName = "Smith") {
  const name = firstName + ' ' + lastName;
  alert(name);
}

sayName('Bob');

22
这如何适用于OP有关作为参数传递的TypeScript对象的默认值的问题?您应该显示一个带有对象参数的示例。
demisx '18

9
没有,但是我在寻找如何在打字稿中提供默认参数时发现了这个问题,没有一个答案可以解决这个问题。在注意到微妙的“对象”参数澄清之前,我也发布了此回复。
抢占

27

销毁参数对象的对象是上面许多答案所针对的对象,Typescript现在具有适当的方法来使其更易于阅读和直观理解。

破坏基础知识:通过破坏对象,可以通过键名从对象中选择属性。您可以定义任意数量的属性,默认值由的基本语法设置let {key = default} = object

let {firstName, lastName = 'Smith'} = myParamsObject;

//Compiles to:
var firstName = myParamsObject.firstName, 
_a = myParamsObject.lastName, 
lastName = _a === void 0 ? 'Smith' : _a;

为参数对象编写接口,类型或类可提高可读性。

type FullName = {
  firstName: string;
   
  /** @default 'Smith' */
  lastName ? : string;
}

function sayName(params: FullName) {

  // Set defaults for parameter object
  var { firstName, lastName = 'Smith'} = params;

  // Do Stuff
  var name = firstName + " " + lastName;
  alert(name);
}

// Use it
sayName({
  firstName: 'Bob'
});


3
我认为这是对该问题的最佳答案!
Gezim

24

不,TypeScript没有自然的方式为定义的对象的属性设置默认值,就像其中一个具有默认值而另一个则没有。您可以定义一个更丰富的结构:

class Name {
    constructor(public first : string, 
        public last: string = "Smith") {

    }
}

并用它代替内联类型定义。

function sayName(name: Name) {
    alert(name.first + " " + name.last);
}

不幸的是,您不能做这样的事情:

function sayName(name : { first: string; last?:string } 
       /* and then assign a default object matching the signature */  
       = { first: null, last: 'Smith' }) {

} 

由于它只会设置默认值,如果nameundefined


我认为这是对该问题的最佳答案,应将其标记为正确答案。
kapad

16

这可能是不涉及冗长构造函数的好方法

class Person {
    firstName?: string = 'Bob';
    lastName?: string = 'Smith';

    // Pass in this class as the required params
    constructor(params: Person) {
        // object.assign will overwrite defaults if params exist
        Object.assign(this, params)
    }
}

// you can still use the typing 
function sayName(params: Person){ 
    let name = params.firstName + params.lastName
    alert(name)
}

// you do have to call new but for my use case this felt better
sayName(new Person({firstName: 'Gordon'}))
sayName(new Person({lastName: 'Thomas'}))

2
@PWKad默认设置为第二行和第三行“ Bob”和“ Smith”
Cameron

3

您可以尝试使用接口并使用默认值进行销毁。请注意,“ lastName”是可选的。

interface IName {
  firstName: string
  lastName?: string
}

function sayName(params: IName) {
  const { firstName, lastName = "Smith" } = params
  const fullName = `${firstName} ${lastName}`

  console.log("FullName-> ", fullName)
}

sayName({ firstName: "Bob" })

0

无需解构,您可以创建默认参数并将其传递给

interface Name {
   firstName: string;
   lastName: string;
}

export const defaultName extends Omit<Name, 'firstName'> {
    lastName: 'Smith'
}

sayName({ ...defaultName, firstName: 'Bob' })
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.