BaseEntityを拡張するエンティティに基づいて構成値を返すファクトリがあります。ただし、ジェネリックパラメーターと同じシグネチャを持つ型を関数から返すことができないという型エラーが発生Collection<A> is not assignable to type Collection<T>
しType A is not assignable to type T
ます。具体的にはTypeとそのです。しかし、この例では同じ定義A
をT
持っていませんか?
type BaseTypes = 'a';
interface Base {
type: BaseTypes;
id: number;
}
interface A extends Base {
type: 'a';
name: string;
}
interface Collection<T extends Base> {
items: T[];
}
function getCollection<T extends Base>(obj: T): Collection<T> | null {
switch (obj.type) {
case 'a':
return getACollection(); // Type Collection<A> is not assignable to type Collection<T>
default:
return null;
}
}
function getACollection(): Collection<A> {
return { items: [] };
}
Typescriptは、タイプガードが機能するために共用体型を必要としBase
ます。これは、派生インターフェイスの基本型ですが、共用体ではないため、コンパイラが絞り込むための共用体はありません。
2番目の問題は、ユニオンを拡張したとしてもTypescriptがジェネリック型を絞り込まないことです(これは将来のリリースで変更されると思いますが、見つかった場合はgithubの問題を投稿します。編集 これは問題ですがどうやらそれを実装する計画はありません)。ただし、パラメーターの型を絞り込んだとしても、パラメーターを絞り込んだだけであり、型ガードは関数の戻り型に影響を与えません。タイプガードは、影響が非常に狭いです。
問題の最も簡単な解決策は、関数に2つの異なるシグネチャを設定Base
することCollection<Base>
です。ジェネリックパラメータを使用するパブリックシグネチャと、を取得して返すジェネリックを含まないプライベートシグネチャです。実装はBase
別の派生の1つの派生を取り込んでコレクションを返す可能性があるため、これは完全にタイプセーフなソリューションではありませんが、現時点で実行できる最善の方法です。
function getCollection<T extends Base>(obj: T): Collection<T> | null
function getCollection(obj: Base): Collection<Base> | null {
switch (obj.type) {
case 'a':
return getACollection();
default:
return null;
}
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加