export type Name = { name: string }
export type Id = { id: number }
export type Value<T> = T extends string ? Name : Id
export function create<T extends string | number>(value: T): Value<T> {
if (typeof value === "string") return { name: value }
return { id: value }
}
私は TypeScript の条件付き型を試しています。条件付き戻り型を持つ関数を記述したいと思います。関数に文字列が渡された場合は Name を返し、そうでない場合は Id を返します。
return ステートメントで次のエラーが発生します。
Type '{ name: T & string; }' is not assignable to type 'Value<T>'.
何が足りないのでしょうか? ありがとう!
編集: Build 2018 での Anders Hejlsberg の講演から直接引用した例:https://youtu.be/hDACN-BGvI8?t=2241
彼は「もう関数のオーバーロードを書く必要はありません...」とさえ述べています。
コードを宣言だけに変更すると、コンパイル エラーはなくなります。
export type Name = { name: string }
export type Id = { id: number }
export type Value<T> = T extends string ? Name : Id
declare function create<T extends string | number>(value: T): Value<T>
const a = create("Bob") // a : Name
const b = create(5) // b : Id
関数シグネチャを宣言できます。では、関数を実際にどのように実装すればよいのでしょうか? という疑問が湧いてきます。
ベストアンサー1
問題は、関数の内部がT
不明であるため、実際に に値を割り当てることができないことですValue<T>
。 1 つのオプションは、型アサーションを使用することです。より型安全なオプションは、入力と出力の型についてより緩和された、別の実装シグネチャを使用することです。
export function create<T extends string | number>(value: T): Value<T> // public signature
export function create(value: string | number): Name | Id { // more relaxed private implementation signature
if (typeof value === "string") return { name: value }
return { id: value }
}