我需要有关通用Obj[K]
的元组的帮助,其中第二项Obj[K][1]
是函数。我该如何解决?
export type ThenArg<T> = T extends Promise<infer U> ? U : T
export type FirstArg<T extends any> =
T extends [infer R, ...any[]] ? R :
T extends [] ? undefined :
T;
type Example<Obj, Keys extends Array<keyof Obj>> = {
[K in Keys[number]]: Obj[K] extends ((...args: any[]) => any) ? FirstArg<ThenArg<ReturnType<Obj[K]>>> : never
}
const Set = {
alpha: ['skip', () => true]
}
type x = Example<typeof Set, ['alpha']>
/**
*
* looking for x = { alpha: boolean }
*
*/
如果Set是一个对象怎么办?会容易吗?
const Set = {
alpha: {
keys: ['a', 'b', 'c'],
fn: () => true
}
}
答案 0 :(得分:1)
要解决此问题,需要对Set
进行一些更改。如所声明的,Set
的项目是string | <some function>
联合的数组,这还不够好。
您可以通过几种方法解决此问题,但是最好的方法是在整个对象中添加const assertion。
const Set = {
alpha: ['skip', () => true],
beta: ['skip', () => Promise.resolve(false)]
} as const
然后您的Example
类型可以实现如下:
type MapReturnTypes<
T extends { [K: string]: readonly [any, (...args: any) => any] },
U extends keyof T
> = {
[K in U]: ThenArg<ReturnType<T[K][1]>>
}
请注意,现在您将多个键指定为联合而不是数组(MapReturnTypes<typeof Set, 'alpha' | 'beta'>
),根据我的经验,这更常见。如果必须要有一个数组,那是一个非常简单的更改:
type MapReturnTypesArray<
T extends { [K: string]: readonly [any, (...args: any) => any] },
U extends Array<keyof T>
> = {
[K in U[number]]: ThenArg<ReturnType<T[K][1]>>
}
我将对正确类型的检查从类型的内部移到了对类型参数的约束,这很明显,如果这些约束不成立,则类型定义不明确。
最后一件事,您可能想从结果类型中删除readonly
,这可以通过-readonly
完成。
type MapReturnTypes<
T extends { [K: string]: readonly [any, (...args: any) => any] },
U extends keyof T
> = {
-readonly [K in U]: ThenArg<ReturnType<T[K][1]>>
}
答案 1 :(得分:0)
对于对象:
<!DOCTYPE html>
<html>
<head>
<title>Assignment1_HTML_L2</title>
</head>
<body>
<div id="circle" ondrop="drop(event)" ondragover="allow(event)" >
<svg width="1000" height="200">
<circle id="c1" cx="70" cy="50" r="50" stroke="green" fill="white" stroke-width="4" style="opacity: 1;" />
<circle cx="200" cy="50" r="50" stroke="yellow" fill="white" stroke-width="4" style="opacity: 1;"/>
</svg>
</div>
<image id="p1" src="https://media.giphy.com/media/l3vR16pONsV8cKkWk/giphy.gif" alt="picture" draggable="true" ondragstart="drag(event)" width="30" height="30" style="opacity: 1;">
</body>
</html>