更新于2020年1月28日
自从TypeScript 2.8引入了条件类型,你现在可以相对容易地进行这种映射:
type A = {
Item1: (x: string, y: number) => Promise<string>,
Item2: () => Promise<number>,
Item3: () => number,
Item4: Promise<string>,
Item5: Promise<number>,
Item6: number
}
type UnpromiseObj<T> = { [K in keyof T]: T[K] extends Promise<infer U> ? U :
T[K] extends (...args: infer A) => Promise<infer R> ? (...args: A) => R :
T[K]
}
type Aprime = UnpromiseObj<A>;
我会保留下面的内容,以便将来后代可以了解在条件类型出现之前你必须经历的疯狂无意义的事情:
2020-01-28 结束更新
虽然没有映射条件类型或类似功能的官方支持,但这并非完全不可能,只是有些困难。让我们试一试。首先,让我们设置一些类型级别的布尔逻辑:
type False = '0';
type True = '1';
type Bool = False | True;
type If<Cond extends Bool, Then, Else> = { '0': Else; '1': Then }[Cond];
所以类型
If<True, Then, Else>
的计算结果为
Then
,类型
If<False, Then, Else>
的计算结果为
Else
。
第一个问题是您需要能够确定类型是否为
Promise
。第二个问题是,您需要能够获取
Promise<T>
的类型
T
。我将通过使用一些在运行时不存在的幻影属性来增强
Object
和
Promise<T>
接口的声明来解决这个问题。
interface Object {
"**IsPromise**": False
}
interface Promise<T> {
"**IsPromise**": True
"**PromiseType**": T
}
那是有些棘手的部分。增强全局接口并不是一个好主意,因为它们存在于每个人的命名空间中。但它具有期望的行为:任何不是
Promise
的
Object
都有一个
"**IsPromise**"
属性,其类型为
False
,而
Promise
则具有一个值为
True
的属性。另外,
Promise<T>
还有一个类型为
T
的
"**PromiseType**"
属性。同样,在运行时这些属性并不存在,它们只是为了帮助编译器。
现在我们可以定义
Unpromise
,将
Promise<T>
映射到
T
并保留任何其他类型。
type Unpromise<T extends any> = If<T['**IsPromise**'], T['**PromiseType**'], T>
还有一个名为MapUnpromise
的函数,它将Unpromise
映射到对象的属性上:
type MapUnpromise<T> = {
[K in keyof T]: Unpromise<T[K]>
}
让我们看看它是否正常工作:
type A = {
Item1: Promise<string>,
Item2: Promise<number>,
Item3: number
}
type Aprime = MapUnpromise<A>
成功了!但是为了实现这一点,我们对类型进行了一些相当不愉快的操作,这可能并不值得。这取决于你的决定!
希望这能有所帮助,祝你好运!
更新1
据我所知,使用函数调用做同样的事情是不可能的。你真的需要像扩展typeof
类型查询这样的东西,但这在目前的TypeScript中并不存在(截至TypeScript v2.5)。
因此,您无法从类型A
中计算出APrime
(请注意,A'
不是有效的标识符。如果您想要,可以使用Aʹ
)。但是,您可以创建一个基本类型,从中可以计算出A
和APrime
:
type False = '0';
type True = '1';
type Bool = False | True;
type If<Cond extends Bool, Then, Else> = [Cond];
type MaybePromise<Cond extends Bool, T> = If<Cond, Promise<T>, T>
我已放弃全局增强,并添加了
MaybePromise<Cond, T>
,其中
MaybePromise<True, T>
计算为
Promise<T>
,
MaybePromise<False, T>
计算为
T
。现在我们可以使用
MaybePromise<>
获取
A
和
APrime
:
type ABase<Cond extends Bool> =
type A = ABase<True>;
type APrime = ABase<False>;
这样就可以了!但是我建议的重构可能不适用于您的用例。这取决于您如何首先获取A
类型。哦,好吧,这是我能做的最好的。希望对您有所帮助。再次祝你好运!
type False
不是= false
而是字符串值0
? - Paul Sachs