ウェブサイト検索

TypeScript - ジェネリックインターフェースを使ったジェネリック関数


ジェネリック関数の戻り値の型を推論したいのですが、TypeScriptにはそれを助けるものがないようです。

次のコードの断片が与えられた場合:

// Generic type for object key access
export type Indexable<T = unknown> = {[key:string]:T}

// My function that does something (usually retrieve data from an API and cast to T)
const myFOO = <T extends Indexable = Indexable>(input:Indexable)=>{
    return input as T // I know this is pointless but its for simplicity sake
}

// My objects type
type MyType = { a: string }

// Invoke the function with some data and MyType
const foo = myFOO<MyType>({'a':'b'})
/*
Return type is: MyType

This is correct as it should be
*/


type MyInferredReturnType=ReturnType<typeof myFOO>
/*
MyInferredReturnType is:
{
    [key: string]: unknown;
}

This is incorrect as I have no way to provide a generic to that function without invoking it
*/

それで、関数に一致するインターフェースを作成し、それを戻り値の型を取得するために使おうとしました:

interface myBAR<T extends Indexable = Indexable>{
    (input:Indexable):T
}

const myBAR: myBAR = <T extends Indexable = Indexable>(input: Indexable) => {
    return input as T // I know this is pointless but its for simplicity sake
}

const bar = myBAR<MyType>({ 'a': 'b' }) //Expected 0 type arguments, but got 1.

type MyInferredBARReturnType = ReturnType<myBAR<MyType>>
 /*
MyInferredBARReturnType is:
{
    [key: string]: unknown;
}
This is incorrect as I my provided type was not passed to the function
*/

それから、インターフェースにジェネリックを関数に追加して Expected 0 type arguments, but got 1 エラーを修正しようとしましたが、ReturnType<myBAR<MyType>> は依然として間違った型を返します

更新:

この問題には2つの可能な解決策がありますが、どちらも完璧ではありません:

  1. 同じ名前のインターフェースを作成してください。ただし、その関数にはインターフェースを使用しないでください。

_

// Generic type for object key access
export type Indexable<T = unknown> = { [key: string]: T }

// My objects type
type MyType = { a: string }

interface myFOO<T extends Indexable = Indexable> {
    (input: Indexable): T
}

const myFOO = <T extends Indexable = Indexable>(input: Indexable) => {
    return input as T // I know this is pointless but its for simplicity sake
}


type MyInferredReturnType = ReturnType<myFOO<MyType>>
//MyInferredReturnType is MyType

const bar = myFOO<MyType>({ 'a': 'b' }) //Expected 0 type arguments, but got 

type t = typeof bar
// t is MyType

私のこの件に関する問題は、関数とインターフェースの間のつながりの欠如です。

  1. コメントからナディア・チブリコワのアイデアを使う:

_

const myBAR: myFOO<MyType> = myFOO

type MyInferredBARReturnType = ReturnType<typeof myBAR>
//MyInferredBARReturnType is MyType

これに関する私の問題は、ジェネリック型を変更したいたびに関数にエイリアスを付ける必要があることです。

より良い達成方法はありますか?