TypesScriptチップ:リターンオフオーバーロードに条件型を使用する.
12170 ワード
導入
数日前、リファクタリングコードを見つけました.
interface IRawUser {
first_name: string
email: string,
id: number,
}
interface User {
name: string,
email: string
print: () => void
}
declare function userFactory(rawUser: IRawUser): User;
function mapRawToUserObject(rawShow: IRawUser[]): User[];
function mapRawToUserObject(rawShow: IRawUser): User;
function mapRawToUserObject(rawShow: IRawUser | IRawUser[]): User | User[] {
if (rawShow instanceof Array) {
return rawShow.map((raw) => userFactory(raw));
}
return userFactory(rawShow);
}
機能mapRawToUserObject
オーバーロードを使用して次のように表現します.IRawUser[]
を返します.User[]
, 我々がそれをシングルで呼ぶならばIRawUser
シングルを返すUser
.あまり複雑ではありませんが、メソッド定義を再構成する良い機会のように見えました.
条件型を作成する
メソッドが受け取る入力の種類を決定する必要があります.
調べる必要のある入力は以下の通りです.
IRawUser
and IRawUser[]
type MapRawResult<T extends IRawUser | IRawUser[]> = any;
次に、条件付き論理を追加します.type MapRawResult<T extends IRawUser | IRawUser[]> = T extends IRawUser ? User : User[]
In plain words: If
T
is assignable toIRawUser
returnUser
otherwise returnUser[]
条件式をこのメソッドに適用します。
現在の方法は次のようになります.
function mapRawToUserObject(rawShow: IRawUser[]): User[];
function mapRawToUserObject(rawShow: IRawUser): User;
function mapRawToUserObject(rawShow: IRawUser | IRawUser[]): User | User[] {
// implementation
}
これでオーバーロードを削除し、ジェネリックパラメーターを追加できますT extends IRawUser | IRawUser[]
), を返します.type MapRawResult<T extends IRawUser | IRawUser[]> = T extends IRawUser ? User : User[]
function mapRawToUserObject<T extends IRawUser | IRawUser[]>(rawShow: T): MapRawResult<T> {
// implementation
}
この時点で、typescriptは私たちが返す価値のタイプについて不満を言うでしょう.コンパイラは、返される値の型を推論できません.この解決方法は、キーワードを使用して期待している型を明示的に表現することです
as
.最終的な方法は次のようになります.
function mapRawToUserObject<T extends IRawUser | IRawUser[]>(rawShow: T): MapRawResult<T> {
if (rawShow instanceof Array) {
return rawShow.map((raw) => userFactory(raw)) as MapRawResult<T>
}
return userFactory(rawShow) as MapRawResult<T>
}
結論
いくつかの値を試してみると、このメソッドは以前と同じように動作しますが、オーバーロードを使用することはできません.
ボーナスとして、私たちは
IRawUser | IRawUser[]
コードクリーナーを作成します.type MapRawArg = IRawUser | IRawUser[];
type MapRawResult<T extends MapRawArg> = T extends IRawUser ? User : User[];
function mapRawToUserObject<T extends MapRawArg>(rawShow: T): MapRawResult<T> {
// ...
}
更なる読書
Reference
この問題について(TypesScriptチップ:リターンオフオーバーロードに条件型を使用する.), 我々は、より多くの情報をここで見つけました https://dev.to/andersonjoseph/typescript-tip-using-conditional-types-to-refactor-overloads-3e60テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol