意外的隐式任何类型与通用类型联合
Unexpected implicit any type from union with generic type
我正在尝试动态推断方法参数,但由于某种原因,我得到了隐式推断的任何类型,即使我在悬停执行方法时确实看到了有效的方法定义,但在我重命名任一方法时它确实有效execute
以外的东西,但我宁愿让它们保持不变,我怎样才能做到这一点?
type CommandBase<T extends BaseCommandInteraction> = ApplicationCommandData & {
execute(interaction: T): unknown | Promise<unknown>
}
export type ContextMenuCommand = CommandBase<ContextMenuInteraction<"cached">> &
(UserApplicationCommandData | MessageApplicationCommandData)
export type SlashCommand = CommandBase<CommandInteraction<"cached">> &
ChatInputApplicationCommandData
type ExtraLegacyCommandData<TArgs> = {
resolveArgs(args: Args, message: Message): TArgs
}
type LegacyCommand<TArgs> = {
type: "LEGACY"
name: string
description: string
execute(message: Message, args: TArgs): unknown | Promise<unknown>
// eslint-disable-next-line @typescript-eslint/ban-types
} & (TArgs extends void ? {} : ExtraLegacyCommandData<TArgs>)
export type Command<TArgs> =
| ContextMenuCommand
| SlashCommand
| LegacyCommand<TArgs>
export function createCommand<TArgs = void>(command: Command<TArgs>) {
return command
}
export default createCommand({
type: "LEGACY",
name: "",
description: "",
execute(message) {
// Type signature shows `execute(message: Message<boolean>, args: void): unknown`
// But `Parameter 'message' implicitly has an 'any' type.`
},
})
编辑:我认为当我定义两个预期的函数参数时推理确实有效,我试图避免必须这样做:
type LegacyCommand<TArgs> = {
type: "LEGACY"
name: string
description: string
execute(
message: Message,
...args: TArgs extends void ? [] : [TArgs]
): unknown | Promise<unknown>
// eslint-disable-next-line @typescript-eslint/ban-types
} & (TArgs extends void ? {} : ExtraLegacyCommandData<TArgs>)
但这也行不通:
// (method) execute(message: Message<boolean>): unknown
async execute(message) { // Parameter 'message' implicitly has an 'any' type.
我发现我的问题与 https://github.com/microsoft/TypeScript/wiki/Breaking-Changes#generic-type-parameters-are-implicitly-constrained-to-unknown 有关,为了解决它,我为我的函数提供了一个明确的约束并稍微调整了我的执行方法
type LegacyCommand<TArgs> = {
type: "LEGACY"
name: string
description: string
execute: (
message: Message,
// Only exposing arguments when array of known type is passed as generic
...args: TArgs extends unknown[] ? [TArgs] : []
) => unknown | Promise<unknown>
// Checking if tuple generic was passed in
} & (TArgs extends [unknown] ? ExtraLegacyCommandData<TArgs> : {})
// Explicit constraint
export function createCommand<TArgs extends unknown[] = []>(
command: Command<TArgs>
) {
return command
}
我正在尝试动态推断方法参数,但由于某种原因,我得到了隐式推断的任何类型,即使我在悬停执行方法时确实看到了有效的方法定义,但在我重命名任一方法时它确实有效execute
以外的东西,但我宁愿让它们保持不变,我怎样才能做到这一点?
type CommandBase<T extends BaseCommandInteraction> = ApplicationCommandData & {
execute(interaction: T): unknown | Promise<unknown>
}
export type ContextMenuCommand = CommandBase<ContextMenuInteraction<"cached">> &
(UserApplicationCommandData | MessageApplicationCommandData)
export type SlashCommand = CommandBase<CommandInteraction<"cached">> &
ChatInputApplicationCommandData
type ExtraLegacyCommandData<TArgs> = {
resolveArgs(args: Args, message: Message): TArgs
}
type LegacyCommand<TArgs> = {
type: "LEGACY"
name: string
description: string
execute(message: Message, args: TArgs): unknown | Promise<unknown>
// eslint-disable-next-line @typescript-eslint/ban-types
} & (TArgs extends void ? {} : ExtraLegacyCommandData<TArgs>)
export type Command<TArgs> =
| ContextMenuCommand
| SlashCommand
| LegacyCommand<TArgs>
export function createCommand<TArgs = void>(command: Command<TArgs>) {
return command
}
export default createCommand({
type: "LEGACY",
name: "",
description: "",
execute(message) {
// Type signature shows `execute(message: Message<boolean>, args: void): unknown`
// But `Parameter 'message' implicitly has an 'any' type.`
},
})
编辑:我认为当我定义两个预期的函数参数时推理确实有效,我试图避免必须这样做:
type LegacyCommand<TArgs> = {
type: "LEGACY"
name: string
description: string
execute(
message: Message,
...args: TArgs extends void ? [] : [TArgs]
): unknown | Promise<unknown>
// eslint-disable-next-line @typescript-eslint/ban-types
} & (TArgs extends void ? {} : ExtraLegacyCommandData<TArgs>)
但这也行不通:
// (method) execute(message: Message<boolean>): unknown
async execute(message) { // Parameter 'message' implicitly has an 'any' type.
我发现我的问题与 https://github.com/microsoft/TypeScript/wiki/Breaking-Changes#generic-type-parameters-are-implicitly-constrained-to-unknown 有关,为了解决它,我为我的函数提供了一个明确的约束并稍微调整了我的执行方法
type LegacyCommand<TArgs> = {
type: "LEGACY"
name: string
description: string
execute: (
message: Message,
// Only exposing arguments when array of known type is passed as generic
...args: TArgs extends unknown[] ? [TArgs] : []
) => unknown | Promise<unknown>
// Checking if tuple generic was passed in
} & (TArgs extends [unknown] ? ExtraLegacyCommandData<TArgs> : {})
// Explicit constraint
export function createCommand<TArgs extends unknown[] = []>(
command: Command<TArgs>
) {
return command
}