TypeScript 関数引数型推論
TypeScriptで関数の引数の型を取得する方法
typeof
演算子とジェネリック関数
TypeScriptでは、typeof
演算子を使って関数の型を取得し、そこから引数の型を推論することができます。
function add(a: number, b: number): number {
return a + b;
}
type AddArguments = typeof add extends (...args: infer A) => any ? A : never;
// AddArgumentsは[number, number]になります
上記の例では、typeof add
で関数の型を取得し、ジェネリック型(...args: infer A) => any
を使って引数の型を推論しています。infer A
は推論された引数の型を表します。
ReturnType
とジェネリック関数
関数の戻り値の型を取得するReturnType
型と組み合わせて、引数の型を推論することもできます。
function add(a: number, b: number): number {
return a + b;
}
type AddArguments = ReturnType<typeof add> extends (a: infer A, b: infer B) => any ? [A, B] : never;
// AddArgumentsは[number, number]になります
この例では、ReturnType<typeof add>
で関数の戻り値の型を取得し、ジェネリック型を使って引数の型を推論しています。
条件付き型
より複雑なシナリオでは、条件付き型を使って関数の引数の型を推論することができます。
type FunctionType<T> = T extends (...args: infer A) => any ? A : never;
function add(a: number, b: number): number {
return a + b;
}
type AddArguments = FunctionType<typeof add>;
// AddArgumentsは[number, number]になります
この例では、FunctionType
という条件付き型を定義し、関数の型を受け取って引数の型を推論しています。
注意
- 条件付き型は複雑なシナリオに対応できますが、可読性が低下する場合があります。適切なバランスを考慮して使用してください。
typeof
演算子は関数の型を取得するのではなく、関数の値を取得します。そのため、ジェネリック型を使って引数の型を推論する必要があります。
function add(a: number, b: number): number {
return a + b;
}
type AddArguments = typeof add extends (...args: infer A) => any ? A : never;
// AddArgumentsは[number, number]になります
? A : never
: 条件付き型を使って、関数が引数を受け取る場合にのみ引数の型を推論します。extends (...args: infer A) => any
: ジェネリック型を使って、関数の引数の型を推論します。infer A
は推論された引数の型を表します。typeof add
: 関数add
の型を取得します。
function add(a: number, b: number): number {
return a + b;
}
type AddArguments = ReturnType<typeof add> extends (a: infer A, b: infer B) => any ? [A, B] : never;
// AddArgumentsは[number, number]になります
extends (a: infer A, b: infer B) => any
: ジェネリック型を使って、関数の引数の型を推論します。ReturnType<typeof add>
: 関数add
の戻り値の型を取得します。
type FunctionType<T> = T extends (...args: infer A) => any ? A : never;
function add(a: number, b: number): number {
return a + b;
}
type AddArguments = FunctionType<typeof add>;
// AddArgumentsは[number, number]になります
ExtractParameters
型
TypeScript 4.5以降では、ExtractParameters
型を使って関数の引数の型を取得することができます。
function add(a: number, b: number): number {
return a + b;
}
type AddArguments = ExtractParameters<typeof add>;
// AddArgumentsは[number, number]になります
infer
キーワードとジェネリック型
ジェネリック型とinfer
キーワードを使って、関数の引数の型を推論することもできます。
type FunctionArguments<T extends (...args: any[]) => any> = T extends (...args: infer A) => any ? A : never;
function add(a: number, b: number): number {
return a + b;
}
type AddArguments = FunctionArguments<typeof add>;
// AddArgumentsは[number, number]になります
keyof
演算子とジェネリック型
関数がオブジェクトを受け取る場合、keyof
演算子とジェネリック型を使って引数の型を推論することができます。
type FunctionArguments<T extends (...args: any[]) => any> = T extends (...args: { [P in infer K]: any }) => any ? K : never;
function add(obj: { a: number; b: number }): number {
return obj.a + obj.b;
}
type AddArguments = FunctionArguments<typeof add>;
// AddArgumentsは"a" | "b"になります
typescript typescript-conditional-types