0

我有这个钩子可以进行 api 调用并缓存整个应用程序中使用的对象。

无需使用一堆辅助函数来从该对象 id 中获取特定值,例如传入对象的键并返回该键值,钩子还可以访问这些对象的数组并可以选择特定的一个,或者它返回应用程序的默认值。

钩子函数,我不会为编写适合打字稿输入和输出的类型定义而苦苦挣扎。

这是我到目前为止所拥有的:

type OddParams = {
    thing: number;
    thing2: number;
    key?: PotatoKey;
}

type Banana = {
    id: string;
    name: string;
}

type Potato = {
    id: string;
    name: string;
    phone: number;
    monkey: Banana;
}

type PotatoKey = keyof Potato;
type Params = OddParams | PotatoKey;

type ObjectType<T> = 
    T extends unknown ? Potato :
    T extends 'id' | 'name' ? string :
    T extends 'phone' ? number :
    T extends 'monkey' ? Banana :
    never;

function getPotato<T extends Params>(desc =  (undefined as unknown) as T): ObjectType<T>{
    console.log(desc);
    return '2' as any
};

getPotato() //returns type Potato (returns the default potato in implemntation )
getPotato('id') //returns type string (would return id of the default potato in implemntation )
getPotato({thing: 2, thing2: 1, key: 'id'}) //returns type string (would return id of potato[2][1] in implemntation )

仍然需要将对象部分添加到 ObjectType 变量中。还在寻找更好的基于键声明的方法,即使它只是字符串参数。上面我T extends 'id'对每个键都做了等等,但是在生产问题中有 20 多个键,所以对于每个返回类型都有一堆三元组最终是非常不可读的。

关于如何实现这一目标的任何想法?

4

1 回答 1

0

您的getPotato函数基本上需要三个不同的签名,以及确定匹配返回类型的三种相应方法。这可以通过函数重载来实现。

第一个和第二个(分别是无参数和字符串参数)非常简单:

function getPotato(): Potato;
function getPotato<K extends keyof Potato>(key: K): Potato[K];

对于第三个重载,您需要从您给它的对象中“获取”key属性的值。params在此之前,该key属性必须是类型keyof Potato

type Params = {
    thing: number;
    thing2: number;
    key: keyof Potato;
}

function getPotato<T extends Params>(params: T): Potato[T['key']]

这表示:paramsis of type T,它必须是Params. 然后作为返回类型,您可以取下钥匙T以找到它的类型Potato

最后,您将需要实际的函数实现,它应该考虑所有这三种情况:

function getPotato(arg?: keyof Potato | Params): Potato | Potato[keyof Potato] {
    if (arg === undefined) {
        return ... // first overload
    }

    if (typeof arg === 'string') {
        return ... // second overload
    }

    const { thing, thing2, key } = arg
    return ... // third overload
};

将所有内容放在一起,我们得到以下代码:

type Banana = {
    id: string;
    name: string;
}

type Potato = {
    id: string;
    name: string;
    phone: number;
    monkey: Banana;
}

type Params = {
    thing: number;
    thing2: number;
    key: keyof Potato;
}

function getPotato(): Potato
function getPotato<K extends keyof Potato>(key: K): Potato[K]
function getPotato<T extends Params>(params: T): Potato[T['key']]
function getPotato(arg?: keyof Potato | Params): Potato | Potato[keyof Potato] {
    // ... 
};

我用以下任务测试了这些类型:

const a: Potato = getPotato()
const b: string = getPotato('id')
const c: number = getPotato({ thing: 2, thing2: 1, key: 'phone' })
const d: Banana = getPotato('monkey')
于 2021-09-13T19:11:15.983 回答