Using TypeScript 4.4.3, I want to be able to explicitly type function parameters to a function that returns a generic. TypeScript is ignoring the types for the parameters to functions that use generics treating them as any
.
The following is a contrived example (not a very useful function) that will show a warning on the input parameter saying it's of type "any" if it's pasted into the TS Playground...
type GenericResult = <T>(input: number) => T
export const returnWhatever: GenericResult = <T>(input) => <T> input
Is the parameter's type defined in the first line supposed to be ignored?
My actual use-case looks like this...
import type { QueryResult } from 'pg'
import pg from 'pg'
const pgNativePool = new pg.native.Pool({
max: 10,
connectionString: import.meta.env.VITE_DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
})
type AcceptableParams = number | string | boolean
type PostgresQueryResult = (sql: string, params?: AcceptableParams[]) => Promise<QueryResult<any>>
const query: PostgresQueryResult = (sql, params?) => pgNativePool.query(sql, params)
type GetOneResult = <T>(sql: string, id: number | string) => Promise<T>
const getOne: GetOneResult = async <T>(sql, id) => {
const { rows } = await query(sql, [id])
return <T> rows[0]
}
const user = await getOne<User>('SELECT * FROM users WHERE id = $1;', 33)
// returns a User
In this example above, the sql parameter must always be a string and the id can be a number or a string.
While the type of the return value for the function is determined where the function is called, it still seemed like a good idea to be able to type the parameters to that function since that part is known.
Possible?
The recommendation from Microsoft is to explicitly type the parameters in the generic function's definition as I have done below with the getOne function below. This doesn't "feel" right because I'm defining the parameter types twice but whatever...
import type { QueryResult } from 'pg'
import pg from 'pg'
const pgNativePool = new pg.native.Pool({
max: 10,
connectionString: import.meta.env.VITE_DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
})
type AcceptableParams = number | string | boolean
type PostgresQueryResult = (sql: string, params?: AcceptableParams[]) => Promise<QueryResult<any>>
const query: PostgresQueryResult = (sql, params?) => pgNativePool.query(sql, params)
type GetOneResult = <T>(sql: string, id: number | string) => Promise<T>
const getOne: GetOneResult = async <T>(sql: string, id: number | string) => {
const { rows } = await query(sql, [id])
return <T> rows[0]
}
const user = await getOne<User>('SELECT * FROM users WHERE id = $1;', 33)
// returns a User