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

Posted

技术标签:

【中文标题】设置作为参数传递的 TypeScript 对象的默认值【英文标题】:Setting default value for TypeScript object passed as argument 【发布时间】:2014-06-12 10:45:18 【问题描述】:
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'; 实际上相当不错 - 它可以处理空字符串、未定义字符串和空值。 @SteveFenton 还有任何虚假的东西。在姓氏的情况下很好,但通常不是一个好主意。这就是 Typescript 将默认值转换为 if(typeof x === "undefined") … 的原因。并不是说你不知道,只是指出 OP 的一般情况。 @IngoBürk 是的,但由于lastName?: string,它只能像 SteveFenton 所说的那样“处理空字符串、未定义字符串和空值”。 同意史蒂夫的观点。通常最好有一个配置参数而不是例如10 个论据。在这种情况下,params.lastName = params.lastName || 'smith'; 是我使用的模式 typescripttutorial.net/typescript-tutorial/…param1: type = defaultValue 【参考方案1】:

Object destructuring 参数对象是上面许多答案的目标,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;
   
  /** @defaultValue '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'
);

【讨论】:

这比公认的答案要好得多。函数体内部的破坏比参数本身更有意义【参考方案2】:

实际上,现在似乎有一个简单的方法。以下代码适用于 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 对象,而是有取消引用的变量。

如果你想让它成为可选的传递任何东西给函数,为类型中的所有键添加一个?,并在类型声明之后添加一个默认的=

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


sayName();

【讨论】:

是否也可以重写此解决方案以使用类似“sayNameSettings”的接口/类? 虽然这行得通,但以这种方式解构参数会使 IMO 难以遵循。 您可以使用 'as' 关键字(在我看来它更具可读性),例如 first='Bob',last='Smith' 作为 first?: string; last?: string 但理想情况下你应该创建一个接口来处理这种情况...... 如果您为参数预定义了接口/类型,您还可以对参数中的类型部分使用 Partial 实用程序类型 有没有办法将选项对象传递给另一个函数?【参考方案3】:

不用解构,你可以创建一个默认参数并传入

interface Name 
   firstName: string;
   lastName: string;


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


sayName( ...defaultName, firstName: 'Bob' )

【讨论】:

【参考方案4】:

这里有一些东西可以尝试,使用接口和使用默认值解构。请注意,“姓氏”是可选的。

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" )

【讨论】:

【参考方案5】:

Typescript 现在支持默认参数:

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

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

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


sayName('Bob');

【讨论】:

这如何适用于 OP 关于作为参数传递的 TypeScript 对象的默认值的问题?您应该展示一个带有对象参数的示例。 它没有,但我在搜索如何在打字稿中提供默认参数时发现了这个问题,但没有一个答案解决了这个问题。在我注意到微妙的“对象”参数澄清之前,我也发布了这个回复。 这不适用于该问题,因为其中已经提到了这一点。 OP 要求 JSON 中的默认值【参考方案6】:

这可能是一个不错的方法,不需要长构造函数

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'))

【讨论】:

@PWKad 默认设置在第二行和第三行,“Bob”和“Smith” 我知道这是一个旧答案,但这个解决方案的一个可能问题是您可以使用 nullundefined 值传递这些参数,因为 Person 类允许这样做。所以写sayName(new Person(firstName: undefined ));在语法上是有效的,但在语义上可能没有任何意义。【参考方案7】:

不,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 时设置默认值。

【讨论】:

我认为这是这个问题的最佳答案,应该标记为正确答案。 对于其他人来说,这不再是真的。查看@Benson 的回答

以上是关于设置作为参数传递的 TypeScript 对象的默认值的主要内容,如果未能解决你的问题,请参考以下文章

传递对象作为未更新的参数[重复]

c#传递引用对象作为参数的时候就没有必要用ref关键字,对吗

从 Typescript POST 到 Web API API,无法传递 JSON 对象

Typescript构造函数和继承

使用默认值键入对象参数

带有 Typescript 的 Vue3 -> 这个对象可能是未定义的