TypeScript: 条件付き戻り型を持つ関数の書き方 質問する

TypeScript: 条件付き戻り型を持つ関数の書き方 質問する
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 }
}

おすすめ記事