[SOLVED] How do you check if a type is an array?

Issue

ANSWER: You can’t

From here I know that to check if a value is a list you can use Array.isArray() but I have an odd situation where I have a query function

export async function query<T = unknown>(sql: string, options?: unknown): Promise<T> {
    const pool = await initializePool()

    const result = await pool.query(sql, options);
    return /* T is of type list */ ? result : [result];
}

I can’t use Array.isArray() on the type and I was wondering if there was some sort of typeof function I can use on the T.

The problem is, pool.query always returns an array and I’d like to destructure it immediately if possible

const initializePool = async () => {
    if (pool) {
        return pool;
    }

    const CREDS = { connectionLimit: 500000, ...MYSQL_CREDS, multipleStatements: true }

    pool = await mysql.createPool(CREDS)
    return pool
}

Solution

TypeScript gets transpiled to JavaScript, and no TypeScript syntax remains in the JS (save for rare things like enums). You cannot have the JavaScript that runs change its behavior depending on what sort of types can be inferred by TypeScript. You need to put the logic in the JavaScript too.

So, you need something like:

export async function query(sql: string, options?: unknown) {
    const pool = await initializePool()

    const result = await pool.query(sql, options);
    return Array.isArray(result) ? result : [result];
}

It’d be theoretically possible to have pool.query examine the passed string (if generic) and infer whether the result is an array (see ts-sql), but it doesn’t look like mysql implements something like that – so there’s no way for you to narrow down whether a passed query will result in result being an array or not. (Not that you need that anyway here, since the return type doesn’t look to depend on that.)

Answered By – CertainPerformance

Answer Checked By – Jay B. (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *