🧧
TypeScript の Type Guard を使って、福袋の中身を判断してみたよ
はじめに
Type Guard(型ガード)っていつまで経っても良く分からんのです 😭
使用頻度も少なくて忘れちゃいそうなので、(今が旬の?)福袋を例に実装してみました。
実装したコードがこちら
福袋の中に「ロッテのパイの実が入っているのか確認したい!」を叶えるコードです。笑
function isObject<T extends Record<string, unknown>>(value: unknown): value is { [P in keyof T]?: unknown } {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
function isString(value: unknown): value is string {
return typeof value === 'string' && value !== null;
}
function isStringArray(value: unknown): value is string[] {
return (
typeof value === 'object' &&
value !== null &&
Array.isArray(value) &&
!value.some((v) => !isString(v))
);
}
type LuckyBag<T = unknown> = T;
function isLuckyBagInPainomi(
luckyBag: LuckyBag,
): luckyBag is LuckyBag<{ lotte: { chocolates: ['painomi'] } }> {
// NOTE: 以下のように、luckyBag をそのまま使うとエラーになります
// console.log(luckyBag.lotte.chocolates)
return (
isObject<{ lotte: object }>(luckyBag) &&
isObject<{ chocolates: string[] }>(luckyBag.lotte) &&
isStringArray(luckyBag.lotte.chocolates) &&
luckyBag.lotte.chocolates.includes('painomi')
)
}
実行した結果がこちら
パイの実が入っていると true
が返ってきます。安全ですね!
console.log(isLuckyBagInPainomi({
lotte: { chocolates: ['painomi'] }
}))
// → true
console.log(isLuckyBagInPainomi({
lotte: { chocolates: ['painomi', 'toppo'] }
}))
// → true
console.log(isLuckyBagInPainomi({
lotte: { chocolates: ['painomi', 'toppo'] },
nestle: { chocolates: ['kitkat'] }
}))
// → true
console.log(isLuckyBagInPainomi({
lotte: { chocolates: ['toppo'] }
}))
// → false
console.log(isLuckyBagInPainomi({
nestle: { chocolates: ['kitkat'] }
}))
// → false
console.log(isLuckyBagInPainomi(''))
// → false
最後に
TypeScript
の Playground にも書いてあるので、良かったら遊んでみてください 😊
Discussion