This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 「typeof 演算子」の型を取得するためのダミー関数 | |
function _dummy() { return typeof ''; } | |
type TypeofType = ReturnType<typeof _dummy>; | |
// 「TypeofType」は TS 4.9 時点では「'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function'」になる | |
// typeof 演算子の結果の文字列に対応する型を書いたマップオブジェクト | |
interface TypeofTypeMap { | |
number: number; | |
string: string; | |
boolean: boolean; | |
bigint: bigint; | |
object: object | null; | |
function: Function; | |
symbol: symbol; | |
undefined: undefined; | |
} | |
// o オブジェクトにあるフィールド name の typeof の結果が typeName になるかをチェックする関数 | |
// ※ もし TypeofType に更新があった場合、「TypeofTypeMap[TypeofName]」が型エラーになるので | |
// 「TypeofTypeMap」のマップを更新する必要がある | |
function isEqualFieldType< | |
T extends object, | |
K extends keyof T, | |
TypeofName extends TypeofType | |
>(o: T, name: K, typeName: TypeofName): o is T & Record<K, TypeofTypeMap[TypeofName]> { | |
return typeof o[name] === typeName; | |
} | |
// o オブジェクトにあるフィールド name が predicate を満たす場合、そのフィールドを O 型とみなす関数 | |
function isEqualFieldTypeObject< | |
T extends object, | |
K extends keyof T, | |
O extends object | |
>(o: T, name: K, predicate: (x: unknown) => x is O): o is T & Record<K, O> { | |
return predicate(o[name]); | |
} | |
interface Foo { | |
foo: string; | |
} | |
interface Hoge { | |
hoge: number; | |
piyo: Foo; | |
} | |
// 子オブジェクトのチェックを関数に分離 | |
function isFoo(o: unknown): o is Foo { | |
if ( | |
typeof o !== 'object' || o == null || | |
!('foo' in o) || !isEqualFieldType(o, 'foo', 'string') | |
) { | |
return false; | |
} | |
o satisfies Foo; | |
return true; | |
} | |
function isHoge(o: unknown): o is Hoge { | |
if ( | |
typeof o !== 'object' || o == null || | |
!('hoge' in o) || !isEqualFieldType(o, 'hoge', 'number') || | |
// 「o.piyo」が存在して「Foo」かどうかをチェック | |
!('piyo' in o) || !isEqualFieldTypeObject(o, 'piyo', isFoo) | |
) { | |
return false; | |
} | |
o.piyo satisfies Foo; // 問題なし | |
o satisfies Hoge; // 問題なし | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment