TypeScript:函数的通用类型将参数视为 "any",尽管另有声明
TypeScript: Generic types for functions treat parameters as "any" despite declaring them otherwise
使用 TypeScript 4.4.3,我希望能够将函数参数显式键入 return 为泛型的函数。 TypeScript 忽略了使用泛型的函数的参数类型,将它们视为 any
.
下面是一个人为的例子(不是一个非常有用的函数),如果它被粘贴到 TS Playground 中,它将在输入参数上显示一个警告,说明它是“任何”类型...
type GenericResult = <T>(input: number) => T
export const returnWhatever: GenericResult = <T>(input) => <T> input
是否应该忽略第一行中定义的参数类型?
我的实际用例是这样的...
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 = ;', 33)
// returns a User
在上面的示例中,sql 参数必须始终是字符串,id 可以是数字或字符串。
虽然函数的 return 值的类型是在调用函数的位置确定的,但能够为该函数键入参数似乎仍然是个好主意,因为该部分是已知的。
可能吗?
根据对话更新示例
type GenericResult = <T = number>(input: T) => T;
export const returnWhatever: GenericResult = (input) => input;
returnWhatever<string>("1");
returnWhatever(1);
returnWhatever<number>("1"); // will error
Typescript 感到困惑,因为它认为您正在覆盖函数参数的类型。我认为你这样做是因为你想重新指定泛型,但你不必这样做,因为你已经在箭头函数的类型上输入了 this。这应该足够了:
type GetManyResults = <T>(sql: string) => Promise<{ body: T[]; }>
export const getMany: GetManyResults = async (sql) => {
const { rows } = await query(sql)
return {
body: rows
}
}
Microsoft 的建议是在通用函数的定义中显式键入参数,就像我在下面对下面的 getOne 函数所做的那样。这“感觉”不对,因为我定义了两次参数类型,但无论如何...
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 = ;', 33)
// returns a User
使用 TypeScript 4.4.3,我希望能够将函数参数显式键入 return 为泛型的函数。 TypeScript 忽略了使用泛型的函数的参数类型,将它们视为 any
.
下面是一个人为的例子(不是一个非常有用的函数),如果它被粘贴到 TS Playground 中,它将在输入参数上显示一个警告,说明它是“任何”类型...
type GenericResult = <T>(input: number) => T
export const returnWhatever: GenericResult = <T>(input) => <T> input
是否应该忽略第一行中定义的参数类型?
我的实际用例是这样的...
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 = ;', 33)
// returns a User
在上面的示例中,sql 参数必须始终是字符串,id 可以是数字或字符串。
虽然函数的 return 值的类型是在调用函数的位置确定的,但能够为该函数键入参数似乎仍然是个好主意,因为该部分是已知的。
可能吗?
根据对话更新示例
type GenericResult = <T = number>(input: T) => T;
export const returnWhatever: GenericResult = (input) => input;
returnWhatever<string>("1");
returnWhatever(1);
returnWhatever<number>("1"); // will error
Typescript 感到困惑,因为它认为您正在覆盖函数参数的类型。我认为你这样做是因为你想重新指定泛型,但你不必这样做,因为你已经在箭头函数的类型上输入了 this。这应该足够了:
type GetManyResults = <T>(sql: string) => Promise<{ body: T[]; }>
export const getMany: GetManyResults = async (sql) => {
const { rows } = await query(sql)
return {
body: rows
}
}
Microsoft 的建议是在通用函数的定义中显式键入参数,就像我在下面对下面的 getOne 函数所做的那样。这“感觉”不对,因为我定义了两次参数类型,但无论如何...
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 = ;', 33)
// returns a User