こんにちは.TypeScript を使ったアプリ開発をしていて,unknown型を絞り込んで型に応じた処理をしたいという場面に遭遇しました.様々勉強になることがあったのでまとめたいと思います!
unknown型を絞り込みたい
型の絞り込みの方法については,こちらの記事 がとても勉強になります.
プリミティブ型かどうかで絞り込みをしたい
例えば,unknown 型がstring 型かどうか絞込をしたい場合は以下のように行います.
const NarrowType = (unknownTypeValue: unknown) => {
if (typeof unknownTypeValue === "string") {
// string 型に応じた処理
}
}
オブジェクト型かどうかで絞り込みをしたい
「あれ,でもオブジェクト型かどうかの絞り込みはどうやるの?typeof で,object
かどうかは分かるけど,その内側のプロパティまでちゃんと含まれているかチェックしたいんだけど...」となりました.
そのような場合は,以下のように行うのが良いみたいです.
type User = {
email: string;
name: string;
};
const NarrowType = (unknownTypeValue: unknown) => {
const user = unknownTypeValue as Record<keyof User, unknown>;
if (typeof user.email === "string" && typeof user.name === "string") {
// User 型に応じた処理
}
}
ここでポイントは,以下の部分です.
const user = unknownTypeValue as Record<keyof User, unknown>;
Record<keys, type>
は,プロパティーのキーが Keys
で構成されていて,各プロパティの型がtype
であるオブジェクトの型を表します.そのため,Record<keyof User, unknown>
は,以下の型を表します.
{
email: unknown;
name: unknown;
};
そして,as
の型アサーションを使って,unknown型のunknownTypeValue
をこの型にします.
ところで,unknown型のunknownTypeValue
に email とか name とか含まれなかったら型アサーションでエラーにならないの?と思うかもしれませんが,型アサーションの対象がunknown型であればエラーは出ないらしいです.
絞り込む処理を共通化したい
「ここまででunknown型を絞り込む処理は書けたけど,何回も絞り込む必要が出てきたから共通化したい」と思いました.そこで便利なのが 型ガード関数 らしいです.
以下のように絞り込む処理を定義して後はそれを呼び出すだけです.
type User = {
email: string;
name: string;
};
// 型ガード関数
const isUserType = (unknownTypeValue: unknown) : unknownTypeValue is User => {
const user = unknownTypeValue as Record<keyof User, unknown>;
if (typeof user.email === "string" && typeof user.name === "string") return true;
else return false;
}
const NarrowType = (unknownTypeValue: unknown) => {
if (isUserType(unknownTypeValue)) {
// ★
// User に応じた処理
}
}
ここで重要なのが,unknownTypeValue is User
という部分です.これがないと,Userの絞り込みが機能せず,// ★ の部分で,unknownTypeValue is of type 'unknown'
などのエラーが出てしまいます.
おわりに
unknown 型を絞り込みたい!ということだけでも,Record や型アサーション,型ガード関数など様々な概念が出てきてとても勉強になりました!同じような場面に直面している方がいましたら,参考にしていただけると嬉しいです!
参考文献