質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

  • TypeScript

    376questions

    TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

TypeScriptで関数の引数に分割代入したときの型指定方法

解決済

回答 1

投稿

  • 評価
  • クリップ 2
  • VIEW 1,674

raccy

score 16831

前提・実現したいこと

TypeScriptはES6の文法を取り入れているため、分割代入ができます。ES6と同じく関数の引数にも分割代入ができます。

function display({name, age}) {
    console.log(`${name}は${age}歳です。`);
}

const taro = { name: "太郎", age: 14 };
display(taro);

const hanako = { name: { family: "鈴木", given: "花子" }, age: "ひみつ" };
display(hanako);

これでは型チェックはされず、間違っているはずのhanakoもコンパイル時に素通りしてしまいます。そこで、型チェックを考えて、次のように書いてみました。

function displayWithType({name: string, age: number}) {
    console.log(`${name}は${age}歳です。`);
}
const taro = { name: "太郎", age: 14 };
displayType(taro);

しかし、この場合は、分割代入の別名という文法になるため、型指定とは見なされません。結果、見に行きたい、namenameになりません。その他、({name: name: string, age: age: number})としてみましたが、文法エラーになるだけでした。

引数への分割代入はどのように型指定をすればいいのでしょうか?

試したこと

その他、型指定する方法としては次のような方法があることがわかっています。

function displayWithDefault({name = "", age = 0}) {
    console.log(`${name}${age}歳です。`);
}
function displayWithObjType(person: { name: string, age: number }) {
    console.log(`${person.name}${person.age}歳です。`);
}
const taro = { name: "太郎", age: 14 };
displayWithDefault(taro);
displayWithObjType(taro);

const hanako = { name: { family: "鈴木", given: "花子" }, age: "ひみつ" };
 // 次の二行は型チェックでコンパイル時にエラー
displayWithDefault(hanako);
displayWithObjType(hanako);

displayWithDefaultはデフォルト値で型推論されて正しく型が指定されますが、デフォルト値が必須になってしまいます。displayWithObjTypeは正統派ですが、せっかくの分割代入が普通の引数への代入になってしまいます。

調査には、下記文献を参考にしました。

分割代入 - JavaScript | MDN
Functions · TypeScript Documentation

TypeScriptの型以外の動作はMDNにあるES2015以降の動作通りです。しかし、TypeScriptのFunctions(関数)に関するドキュメントには分割代入については書いていません。

その他、TypeScript 1.7 · TypeScript#Improved checking for destructuring object literalに分割代入でのデフォルト値により型推論がありましたが、型指定については見つけられませんでした。

補足情報(言語/FW/ツール等のバージョンなど)

TypeScript 2.1.5
コンパイルオプションでstrictNullChecksは有効

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+4

ん~。やるとしたらこんな感じでしょうか。

function displayWithType({name, age }: {name: string, age: number}) {
    console.log(`${name}は${age}歳です。`);
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/23 20:53

    分割代入の所全体を型指定すればいいと言うことですか…なるほど…
    しかし、nameとかを二回も書くのはなんともこそばゆいんですが、他に方法は無いんでしょうか…

    キャンセル

  • 2017/01/23 21:13

    やりたいことはすごく分かるんですが、
    多分用意されてないんじゃないかなぁと思います。
    他に方法があるとしたら「interface」の実装や、
    「class」作って「constructor」とかでごにょごにょ。。←コレのほうが気持ち悪い。。

    デフォルト値を設定するパターンをよく見かけます。
    というか引数の型にオブジェクト型リテラルをそのまま使わない設計にするのかもしれませんね。

    キャンセル

  • 2017/01/24 06:07

    ちゃんとするにはinterfaceを用意しておくのが一番いいのかも知れませんね…。再利用もできますし。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • TypeScript

    376questions

    TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。