type NotAPromise<T> = T & { then?: void };
function f<T>(o: NotAPromise<T>) {
}
f(1); // ok
f({}); // ok
f(Promise.resolve(2));
Argument of type 'Promise<number>' is not assignable to parameter of type 'NotAPromise<Promise<number>>'.
Type 'Promise<number>' is not assignable to type '{ then?: void | undefined; }'.
Types of property 'then' are incompatible.
Type '<TResult1 = number, TResult2 = never>(onfulfilled?: ((value: number) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<...>) | null | undefined) => Promise<...>' is not assignable to type 'void'.
type ObjectNotPromise<T extends object> = T extends Promise<unknown>
? never
: T;
function myFn<TArg extends object>(myArg: ObjectNotPromise<TArg>) {
}
myFn({}); // valid
myFn(2); // not valid
myFn(Promise.resolve("asdf")); // not valid
如果你也不想允许promise的数组(如果你试图捕捉丢失的await s,这是一种常见的情况):
type ObjectNotPromise<T extends object> = T extends Promise<unknown>
? never
: T extends Promise<unknown>[]
? never
: T;
// not valid. though would be valid with the previous version of the type
myFn([Promise.resolve("foo")]);
2条答案
按热度按时间x6yk4ghg1#
是的,有点像。有一个技巧可以通过使用可选的void类型声明这些属性来禁止具有某些属性的对象类型:
hjzp0vay2#
我在寻找类似的解决方案时偶然发现了这个问题。由于接受的答案并没有将参数约束为对象类型,这里有一个适合我的版本。它将接受除Promise之外的任何对象。
如果你也不想允许promise的数组(如果你试图捕捉丢失的
await
s,这是一种常见的情况):这里唯一的警告是空数组是无效的。我不知道如何解决这个问题。一个解决方案是将数组转换为一个类型。例如。