使用 Promise 的 TypeScript 异步类型保护
Posted
技术标签:
【中文标题】使用 Promise 的 TypeScript 异步类型保护【英文标题】:TypeScript async type guard using Promise 【发布时间】:2018-01-01 20:53:28 【问题描述】:我正在尝试定义一个异步类型保护。我可以同步执行以下操作:
class Foo
public type = 'Foo';
// Sync type guard:
function isFoo(obj: any): obj is Foo
return typeof obj.type !== 'undefined' && obj.type === 'Foo';
function useFoo(foo: Foo): void
alert(`It's a Foo!`);
const a: object = new Foo();
if (isFoo(a)) useFoo(a);
但我不确定如何执行相同的异步操作。这是我尝试过的:
class Bar
public getType = () => new Promise(resolve =>
setTimeout(() => resolve('Bar'), 1000);
);
// Async type guard:
async function isBar(obj: any): Promise<obj is Bar>
if (typeof obj.getType === 'undefined') return false;
const result = await obj.getType();
return result === 'Bar';
function useBar(bar: Bar): void
alert(`It's a Bar!`);
const b: object = new Bar();
isBar(b).then(bIsBar =>
if (bIsBar) useBar(b);
);
Try it here
任何帮助将不胜感激!
【问题讨论】:
它似乎还不是一个功能。也许你可以submit the idea? 当使用 tsc 2.0.9 和节点 7.7.3 定位 es6 时,这似乎工作正常。 【参考方案1】:不,您不能从函数的直接范围之外访问受保护的参数。所以一旦你返回一个承诺,你就不能再保护obj
了。这听起来像是一个简洁的功能想法,正如@Paleo 建议的那样,如果还没有的话,你应该提交它。
但它可能无济于事;即使您可以表达跨范围的类型保护,编译器也可能会再次扩大类型,因为值可能会发生变异:
class Bar
public getType = () => new Promise(resolve =>
setTimeout(() => resolve('Bar'), 1000);
);
public barProp: string; // added to distinguish structurally from NotBar
class NotBar
public getType = () => new Promise(resolve =>
setTimeout(() => resolve('NotBar'), 1000);
);
public notBarProp: string; // added to distinguish structurally from Bar
function useBar(bar: Bar): void
alert(`It's a Bar!`);
function useNotBar(notBar: NotBar): void
alert(`Nope, not a Bar.`)
var b: Bar | NotBar = new Bar();
if (b instanceof Bar)
useBar(b); // narrowed to Bar, no error
isBar(b).then(bIsBar =>
useBar(b); // error! widened to Bar | NotBar again
)
作为一种可能的解决方法,您可以发明自己的“类型保护”对象并将其传回,尽管使用起来不那么愉快:
type Guarded<Y, N = any> = matches: true, value: Y | matches: false, value: N ;
function guarded<Y, N = any>(v: Y | N, matches: boolean): Guarded<Y, N>
return matches ? matches: true, value: <Y>v : matches: false, value: <N>v ;
// Async type guard:
async function isBar<N extends getType?: () => Promise<any> = any>(obj: Bar | N): Promise<Guarded<Bar, N>>
if (typeof obj.getType === 'undefined') return guarded(obj, false);
const result = await obj.getType();
return guarded(obj, result === 'Bar');
isBar(b).then(bIsBar =>
if (bIsBar.matches) useBar(bIsBar.value);
);
isBar<NotBar>(b).then(bIsBar =>
if (bIsBar.matches) useBar(bIsBar.value); else useNotBar(bIsBar.value);
);
【讨论】:
以上是关于使用 Promise 的 TypeScript 异步类型保护的主要内容,如果未能解决你的问题,请参考以下文章
使用 typescript 在 Redux thunk 中返回一个 Promise
使用 angularJS 和 Typescript 的 Promise
使用 Angular 1 应用程序在 Typescript 中管理 ES6/2015 Promise
使用 typescript 中 Promise 中的值设置 React.FC 状态