引数として渡される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';は実際にはかなり良いです-それは空の文字列、未定義の文字列とnull値を処理します。
— フェントン2014

@SteveFentonそして何でも悪い。姓の場合は問題ありませんが、通常はお勧めできません。Typescriptがデフォルト値をに変換するのはそのためif(typeof x === "undefined") { … }です。あなたはそれを知らないのではなく、OPの一般的なケースを指摘するだけです。
— IngoBürk14年

1
@IngoBürkはtrueですlastName?: stringが、SteveFentonが「空の文字列、未定義の文字列、およびnull値を処理する」と言った場合にのみ、これが発生する可能性があります。
— AJP

@AJP Typescript内、はい。しかし、それは単にコンパイル時です。いずれにせよ、私が言ったように、一般的なケースのシナリオを指摘するだけです:)
— IngoBürk14年

2
ここのスティーブに同意します。ごく一般的には、たとえば10個の引数ではなく、単一のconfig引数を使用する方が適切です。この場合params.lastName = params.lastName || 'smith';、私が使用するパターンです
— basarat 2014

回答:


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 2017年

4
これは機能しますが、引数をこのように分解すると、IMOをたどることが難しくなります。
— PW Kad

1
{first = 'Bob'、last = 'Smith'}のような 'as'キーワード(私の意見ではより読みやすい)を{first ?: string;として使用できます。last ?: string}しかし、理想的には、このケースを処理するためのインターフェイスを作成する必要があります...
— Frohlich

1
オプションオブジェクトを別の関数に渡す方法はありますか?
— 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');

21
これは、引数として渡されるTypeScriptオブジェクトのデフォルト値に関するOPの質問にどのように適用されますか?オブジェクト引数を使用した例を示す必要があります。
— demisx

9
そうではありませんが、typescriptで一般的にデフォルトのパラメーターを提供する方法を探していたときにこの質問を見つけました。微妙な「オブジェクト」パラメーターの明確化に気付く前に、この応答も投稿しました。
— 2018年

27

オブジェクトの破壊パラメータオブジェクトは、上記の回答の多くが目指していると活字体が今読んで直感的に理解することがはるかに容易にする代わりにメソッドを持っているものです。

基本の破壊:オブジェクトを破壊することにより、キー名でオブジェクトからプロパティを選択できます。必要なプロパティをいくつでも定義でき、デフォルト値はの基本的な構文によって設定されます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' }) {

} 

である場合nameにのみデフォルトを設定するためundefined。


これがこの質問に対する最良の答えであり、正解としてマークする必要があると思います。
— 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デフォルトは2行目と3行目に設定されています。「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' })
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.