我有一个函数接受一个对象,其中每个prop是一个promise。它等待所有的承诺完成然后返回一个具有相同道具但现在已解决的值的新对象。
resolved_props.company
应该是string
,而不是Promise<string>
// TODO: fix the types on this
function promise_props<T>(obj:T):Promise<T> {
const keys = Object.keys(obj)
const len = keys.length
const awaitables = new Array<T>(len)
for (var i = 0; i < len; i++) awaitables[i] = (obj as any)[keys[i]]
return Promise.all(awaitables).then((results) => {
const byName:any = {}
for (var i = 0; i < len; i++) byName[keys[i]] = results[i]
return byName
})
}
答案 0 :(得分:7)
你的类型不够准确,TypeScript编译器无法弄清楚它们不是那时的承诺。
你需要的是这样的东西:
async function promise_props<T>(obj: {[key: string]: Promise<T>}): Promise<{[key: string]: T}> {
const keys = Object.keys(obj);
const awaitables = keys.map(key => obj[key]);
const values = await Promise.all(awaitables);
const result: {[key: string]: T} = {};
keys.forEach((key, i) => {
result[key] = values[i];
});
return result;
}
但只有当你的对象具有相同类型的promise时才会起作用,例如:
{
company: Promise.resolve("company"),
page: Promise.resolve("1")
};
我不确定是否可以在当前的TypeScript版本中使用各种承诺类型,但正如Tao建议的那样,您可以使用TypeScript 2.8中的新功能来实现它:
type UnPromisifiedObject<T> = {[k in keyof T]: UnPromisify<T[k]>}
type UnPromisify<T> = T extends Promise<infer U> ? U : T;
async function promise_props<T extends {[key: string]: Promise<any>}>(obj: T): Promise<UnPromisifiedObject<T>> {
const keys = Object.keys(obj);
const awaitables = keys.map(key => obj[key]);
const values = await Promise.all(awaitables);
const result = {} as any;
keys.forEach((key, i) => {
result[key] = values[i];
});
return result as UnPromisifiedObject<T>;
}
async function main() {
const x = {
company: Promise.resolve("company"),
page: Promise.resolve(1)
};
const res = await promise_props(x);
const company = res.company; // company is a string here
const page = res.page; // page is a number here
}
如您所见,正确推断了返回类型。我认为可以改进该方法的实现。我无法找到一种方法来实例化返回类型的实例并使用any
,但是虽然编译器无法推断它,但它类型安全,因为我们解决了所有的承诺。
答案 1 :(得分:6)
在打字稿2.8之后,我能够使用以下策略
Option Explicit
Sub consolidate()
Const SHEET_NAME = "Archer Search Report"
Const NO_OF_COLS = 101
Dim wb As Workbook, ws As Worksheet
Dim irow As Long, iLastRow As Long, c As Long, count As Long
Set wb = ThisWorkbook
Set ws = wb.Sheets(SHEET_NAME)
iLastRow = ws.Range("A" & Rows.count).End(xlUp).Row
' scan up sheet
For irow = iLastRow - 1 To 2 Step -1
' if same id below
If ws.Cells(irow + 1, 1) = ws.Cells(irow, 1) Then
' scan across
For c = 1 To NO_OF_COLS
' if blank copy from below
If Len(ws.Cells(irow, c)) = 0 Then
ws.Cells(irow, c) = ws.Cells(irow + 1, c)
End If
Next
ws.Rows(irow + 1).Delete
count = count + 1
End If
Next
MsgBox iLastRow - 1 & " rows scanned" & vbCr & _
count & " rows deleted from " & ws.Name, vbInformation
End Sub
用法如下
export type Await<T> = T extends Promise<infer U> ? U : T
export type AwaitProps<T> = {[P in keyof T]: Await<T[P]>}
export async function concurrent<T>(obj: T): Promise<AwaitProps<T>> {
const keys = Object.keys(obj)
const awaitables = keys.map(key => obj[key])
const values = await Promise.all(awaitables)
const result = {}
keys.forEach((key, i) => result[key] = values[i])
return <AwaitProps<T>>result
}