关于 TypeScript 泛型,T[number][] 是否等于 T?
我正在编写一个 TypeScript 方法,该方法接受一个泛型 T,该泛型继承自一个 MySQL 结果数组。我通过一个方法进行映射,该方法返回 T 的元素的 Promise(T[number]),然后通过 Promise.all 等待它们。这应该会得到一个 T 的元素数组,T[number][],我原以为这会简化为 T。但是当我返回结果时,会出现错误 Type 'T[number][]' is not assignable to type 'T'。
我这里做错了什么?T[number][] 不等于 T 吗?
这是一个简化的 TS playground 重现。
export async function executeAllParallel<
T extends readonly (QueryResult | Record<string | number, unknown>[])[],
>(
dataAccountId: string,
queries: QueryOptions[],
retries: number = 0,
): Promise<T> {
const connection: mysql.PoolConnection =
await poolCluster.getConnection(dataAccountId);
try {
await connection.beginTransaction();
const results: T[number][] = await Promise.all(
queries.map((query) =>
connection.execute<T[number]>(query).then((result) => result[0]),
),
);
await connection.commit();
// Type 'T[number][]' is not assignable to type 'T'.
return results;
} catch (error) {
await connection.rollback();
if (retries <= 1) throw error;
connection.release();
return executeAllParallel(dataAccountId, queries, retries - 1);
} finally {
connection.release();
}
}
答案#1
TypeScript 可以表达,我假设你正在使用元组类型。
元组类型是另一种数组类型,它确切地知道包含多少元素,以及在特定位置包含哪些类型。
作为例子,考虑这个 T:
type SpecificArray = [number, boolean, string];
这定义了一个具有正好三种特定类型元素的数组。
type T1 = T[number];
编译器所能做的最好就是推断 T1=number | boolean | string。
type T2 = T1[];
那是 (number | boolean | string)[],有关单个元素限制的信息已经丢失。
所以不,T[number][] 不会是 T。
总体而言,你的代码假设各个 queries 将返回满足对应 T 索引的类型,除非你想进一步限制 QueryOptions 的类型,否则你能做的最好的事情就是手动将 results 类型转换为 T。
