2017-04-01 19 views
3

にオプションの単一のプロパティを確認します:のは、私はPerson型を持っているとしましょう...</p> <p>を活字体、2.2で活字体

interface Person { 
    name: string; 
    hometown: string; 
    nickname: string; 
} 

そして、私は、人を返す関数を作成したいのですがニックネームは必要ありません:

function makePerson(input: ???): Person { 
    return {...input, nickname: input.nickname || input.name}; 
} 

inputの種類は?私はPersonと同じタイプを指定する動的な方法を探していますが、nicknameはオプションです(nickname?: string | undefined)。私がこれまでに考え出した最も近いものはこれです:

type MakePersonInput = Partial<Person> & { 
    name: string; 
    hometown: string; 
} 

が、私は必要はなく、あるものをされているすべての種類を指定する必要があるため、それは、私が探しているかなりのものではないのですオプション。

答えて

0

TypeScript 2.4以降。利用できる別のオプションがありますようにタイプの減算のスレッドでGitHubのユーザーahejlsbergによって提案されたように1、それは、見えます:https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-307871458

type Diff<T extends string, U extends string> = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T]; 
type Overwrite<T, U> = { [P in Diff<keyof T, keyof U>]: T[P] } & U; 

interface Person { 
    name: string; 
    hometown: string; 
    nickname: string; 
} 
type MakePersonInput = Overwrite<Person, { 
    nickname?: string 
}> 
function makePerson(input: MakePersonInput): Person { 
    return {...input, nickname: input.nickname || input.name}; 
} 

インテリセンスによると、MakePersonInputは同等です:

Aに見える
type MakePersonInput = { 
    name: string; 
    hometown: string; 
} & { 
    nickname?: string; 
} 

少し面白いが、絶対に仕事を終わらせる。

私はそれがどのように機能するか理解し始める前に、その下に、Diffタイプをしばらく見ておく必要があります。

1

良い質問です。私はオプションのnicknameプロパティを持つベースインターフェイスを作成し、そのベースインターフェイスを拡張してその存在を要求します。あなたが本当に記述していることは、人々(すなわち人の二つの異なる「種類」で[OK]をうまく

interface MakePersonInput { 
    name: string; 
    hometown: string; 
    nickname?: string; 
} 

interface Person extends MakePersonInput { 
    nickname: string; 
} 
1

:まだ同じタスクを遂行しながら、だから、本質的に、それは、構造的にあなたが探しているもののですタイプ)。普通の人とニックネームの人。

interface Person { 
    name: string; 
    hometown: string; 
} 

interface NicknamedPerson extends Person { 
    nickname: string; 
} 

次に、あなたが本当に愛称人が、ちょうど人はあなただけの人インターフェイスを実装したくない場合には

あなただけの一人・インタフェースが非愛称人のために異なる実装をしているにハングアップしたい場合は、これを行うには別の方法:

interface Person { 
    name: string; 
    hometown: string; 
    nickname: string; 
} 
class NicknamedPerson implements Person { 
    constructor(public name: string, public hometown: string, public nickname: string) {} 
} 

class RegularPerson implements Person { 
    nickname: string; 
    constructor(public name: string, public hometown: string) { 
     this.nickname = name; 
    } 
} 

makePerson(input): Person { 
    if(input.nickname != null) { 
     return new NicknamedPerson(input.name, input.hometown, input.nickname); 
    } else { 
     return new RegularPerson(input.name, input.hometown); 
    } 
} 

これはあなたがある(まだニックネームを割り当てることができますニックネームがない場合は人名だけ)、Personインターフェースの契約を維持してください。それは本当にあなたがインターフェイスを使用するつもりかともっと関係しています。コードはニックネームを持つ人を気にしますか?もしそうでなければ、最初の提案はおそらく良いでしょう。

+0

こんにちは...これは私が尋ねた質問にはすばらしい応答ですが、私が実際に解決しようとしていることはあまりありません:/質問の単純化のために申し訳ありません。私が聞いたところでは...基本的に、すべての人はニックネームを持っていましたが、私はこの機能にそれを必要としたくありません。提供されていない場合は、単に 'name'入力を使用します。 – DallonF

+0

私が主張していた第2の選択肢をよりよく説明するために私の答えを編集しました。私たちがまだ同じページにいないかどうか教えてください。 RegularPersonコンストラクタは、 "ニックネーム"の値をinputの "name"の値と等しくすることに注意してください。 –

+0

ここの 'input'はまだタイプがありません。これはこの質問の難しい部分です...私がやっていることは、TypeScriptではまだできません。私は私が見つけたもので自己解決するつもりだと思う。 – DallonF

1

多くの掘り出しの後、私はちょうどタイプスクリプトではできません... まだspread/rest typesが土地にあるとき、私はそれが{ ...Person, nickname?: string }の行に沿った何かの構文であると思います。今の

、私はを必要とされるプロパティを宣言し、より詳細なアプローチを行ってきた:

type MakePersonInput = Partial<Person> & { 
    name: string; 
    hometown: string; 
}; 
function makePerson(input: MakePersonInput): Person { 
    return {...input, nickname: input.nickname || input.name}; 
} 

これは、残念ながら私はPersonに多くの必要なプロパティを追加するたびにMakePersonInputを更新するために私を必要としますが、 makePersonにタイプエラーが発生するため、これを忘れることは不可能です。

関連する問題