2.4

2017-06-19 2 views
2

私は私のPersonインターフェースに準拠している必要がありフィクスチャ与える関数があります。2.4

interface Person { 
    name: string 
    email: string 
    age?: number 
} 

function makePerson(override: Partial<Person> = {}): Person { 
    return { 
    name: 'Jim', 
    email: '[email protected], 
    age: 24, 
    ...override, 
    } 
} 

は活字体2.3では、これは正常に動作しますが、私は、特定のキー無効にするために、このような機能のものを呼び出すことができます。

const myPerson = makePerson({name: 'Bob'}) 
// { 
// name: 'Bob', 
// email: '[email protected], 
// age: 24, 
// } 

をしかし、2.4にアップデートした、コンパイラは、このようなエラーを与える:

Type '{ name: string | undefined; email: string | undefined; age: number | undefined; }' is not assignable to type 'Person'. 
    Types of property 'name' are incompatible. 
    Type 'string | undefined' is not assignable to type 'string'. 
     Type 'undefined' is not assignable to type 'string'. 

それはやっている理由は、私が見ることができますこの場合、JavaScriptでは、undefinedに設定された複数のキーのうちの1つを持つオブジェクトを渡すことで、オブジェクトのいずれかのキーをオーバーライドすることができます。これはデフォルトをオーバーライドし、Personに準拠しないオブジェクトを返します。これは、キーを省略すると、undefinedと異なるためです。

最大のタイプの安全性を維持しながら、以前は何を達成する方法がありますか?

+0

おそらく 'Overwrite'があなたを助けてくれるかもしれません.nirendyとahejlsbergの実装については、[#12215](https://github.com/Microsoft/TypeScript/issues/12215)をご覧ください。 – Tycho

+0

これは良い機能のようですが、私はこの問題に対処していないと思います。問題はTS2.4が部分的に実装されていることと、 'undefined'を実際に' undefined'に設定されたキーやキーを省略することができる 'undefined'をどのように解釈するのかについて厳しくなっていることです。 2.3はそれほど難解ではなく、オーバーライドのキーが 'undefined 'であれば省略されており、デフォルトを上書きしないことを前提としています。 – harryg

+0

申し訳ありませんが、私は今参照してください。私は 'strictNullChecks'を無効にすることでこれを動作させることができました。理想的ではないかもしれませんが、それは何かです。 'Overwrite'は幸いにも機能リクエストではありません。定義を追加すると機能します。 :) – Tycho

答えて

2

おそらくこれは最善の答えではありませんが、オブジェクトの広がりを避け、それぞれのフィールドを設定することで回避できます。

function makePerson(override: Partial<Person> = {}): Person { 
    return { 
    name: override.name !== undefined ? override.name : 'Jim', 
    email: override.email !== undefined ? override.email : '[email protected]', 
    age: override.age !== undefined ? override.age : 24 
    } 
} 
+0

ええ、それはオプションだと思います。たぶん、これを行うジェネリックスを取る 'applyOverrides'関数を定義することです。しかし理想的ではない。 – harryg

0

この回答少なくとも理論だけのように見える - それは動作しますが。

タイプをプロパティのセットとして表示し、これらのプロパティのサブセットである(パワーセットすべてのプロパティ)を呼び出すことができます。タイプは表現することができます。

type Person_Powerset = 
    {} | 
    {email: string} | { name: string } | { age: number} | 
    {name: string, email: string} | {name: string, age: number} | {email: string, age: number} | 
    {name: string, email: string, age: number}; 

私は活字体は、例えば、このタイプを構築できるように、タイプレベルで十分に表現豊かであるかどうかわかりませんPowerset<Person>のように。