typescriptには「ダブルアサーション」というものがあります。
できるだけ使うことを避けた方が良いですが、テクニックとして知っておくのが良いかと思います
アサーションとは
アサーション自体が型を強制的に変換する機能です。
以下の例を見てください。
type User = {
id: string;
name: string;
isAdmin?: boolean;
}
type AdminUser = User & {
isAdmin: true;
}
function userToAdminUser(user: User): AdminUser {
user.isAdmin = true;
// Type 'User' is not assignable to type 'AdminUser'.
return user;
}
userToAdminUser
はuser
をAdminUser
にして返します。
しかし、return user;
でエラーが出ています。
User
型からAdminUser
型に変換することはできないからです。
このエラーを解決するのが、アサーションです。
return user as AdminUser;
as AdminUser
を追加することによって userをAdminUser
型に変換することができます。
ダブルアサーションとは
上のようなパターンはエラーを消すことができました。
しかし、以下の例はどうでしょうか。
type User = {
id: string;
name: string;
isAdmin?: boolean;
}
type AdminUser = {
id: string;
adminName: string;
isAdmin: true;
}
function numberToString(hoge: User): AdminUser {
hoge.isAdmin = true
// Conversion of type 'User' to type 'AdminUser' may be a mistake because neither type sufficiently overlaps with the other.
return hoge as AdminUser;
}
アサーションしているはずなのに、エラーが出ました。
上の例と違うところはAdminUser
型がUser
型のサブタイプではないということです。
実はtypescriptのアサーションは何でもかんでも型変換できるわけではなく、型変換したい型がサブタイプもしくはスーパータイプである必要があります。
サブタイプでない型へ変換するにはどうすれば良いでしょうか?
ここで、ダブルアサーションの出番です。
return hoge as unknown as AdminUser;
これでエラーが出なくなりました。
ダブルアサーションは一度unknown型にアサーションしてから、本来型変換したい型に変換します。
全ての型はunknown型のサブタイプなので、どんな型に変換してもエラーが出ません。
any型でも大丈夫です。
2回アサーションをしているため、ダブルアサーションという呼び方になってます。
なぜ、ダブルアサーションは避けるべきなのか
ダブルアサーションを避けた方が良い理由を一言で述べると、型安全が守られないことです。
例に挙げたコードでもhoge
はAdminUser型なのにadminName
を持っていません。
function numberToString(hoge: User): AdminUser {
hoge.isAdmin = true
// adminNameを設定していないのにエラーが出ていない
return hoge as unknown as AdminUser;
}