あなたはコードを正しく表現していると思いますし、TypeScriptが有効な割り当てを妨げていると思います。 O
が
type OPrime = {
id: number;
kind: "a" | "b"
}
と構造的に同一である必要があり、create()
はタイプOPrime
の値を返すために、それはO
に割り当て可能でなければならないことを、あなたと私には明らかです。悲しいかな、TypeScriptはOPrime
に割り当て可能なものとしてO
を見ていますが、その逆はありません。
あなたのための最も簡単な回避策は、型アサーションを使用することです:
function create(id: number, kind: "a" | "b"): O {
return {
id: 1,
kind: kind
} as O; // assertion
}
タイプのアサーションは、一般的に安全ではありませんが、あなたは、コンパイラよりも多くを知っているときに便利ですが、式の種類について把握することができます。しかし、コンパイラが警告している正当なバグと、コンパイラが有効な式を認識できないという違いを伝えるのは難しいです。この場合、私はあなたが正しいと判断していることをかなり確信しています。コンパイラは誤ったエラーを報告しています。
これは、TypeScriptの場合、intended behaviorです。 O
とOPrime
は同じですが、コンパイラがこれを認識するためには余分な作業が必要です。 通常これはnot warrantedです。なぜなら、2つの共用体構成要素が同じ名前の単一のプロパティの型によってのみ異なることはまれであるからです。ほとんどの場合(場合によっては実際のおもちゃ以外の使用例でも)、A
とB
のタイプには他のタイプがあります。たとえば:
interface AExtra extends I {
kind: "a";
name: string;
}
interface BExtra extends I {
kind: "b";
age: number;
}
type OExtra = AExtra | BExtra;
は、今では労働組合の値を持つプロパティを持つ単一の非組合型としてOExtra
を表現することはできなくなりました。 OExtraPrime
考えてみましょう:
type OExtraPrime = {
id: number;
kind: "a" | "b";
name?: string;
age?: number;
}
どのOExtra
がOExtraPrime
に割り当て可能であることは事実ですが、その逆はありません。したがって、一般的なプラクティスでは、O
とOPrime
の間の同等の種類が表示されないので、コンパイラはそれを確立することを煩わしくはありません。だからあなたができるのはタイプアサーションです。
希望します。がんばろう!