Type intersection issue when switching to TypeScript 4.8

63 Views Asked by At

I'm moving from TypeScript 4.5 to 4.8 and stumbled upon the following issue.

I have these two types:

export interface IQueryConfig {
    text: string;
    values?: any[];
}

export interface IQueryResult<T> {
    rows: T[];
    rowCount: number;
}

They are a wrapper around the @types/pg package. I also have:

export interface IDbClient {
    query<TResult = any>(queryConfig: IQueryConfig | string): Promise<IQueryResult<TResult>>;
}

And finally, I have this function:

export const dbClient: IDbClient = {
    query: async q => await pool.query(q)
}

On 4.5 this was fine, but on 4.8, after stricter type narrowing was introduced I get an error:

Type 'Promise<QueryResult<QueryResultRow>>' is not assignable to type 'Promise<IQueryResult<T>>'.
  Type 'QueryResult<QueryResultRow>' is not assignable to type 'IQueryResult<T>'.
    Types of property 'rows' are incompatible.
      Type 'QueryResultRow[]' is not assignable to type 'T[]'.
        Type 'QueryResultRow' is not assignable to type 'T'.
          'T' could be instantiated with an arbitrary type which could be unrelated to 'QueryResultRow'.ts(2322)

Interestingly enough, if I change it to this it works:

export const dbClient: IDbClient = {
    query: async q => {
        const result = await client.query(q);
        return result;
    }
}

Here are the types of pg just in case:

export interface QueryResultBase {
    command: string;
    rowCount: number;
    oid: number;
    fields: FieldDef[];
}

export interface QueryResultRow {
    [column: string]: any;
}

export interface QueryResult<R extends QueryResultRow = any> extends QueryResultBase {
    rows: R[];
}
0

There are 0 best solutions below