You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于数组元素的动态类型:为扩展元组实现TypeScript智能提示

实现带智能提示的扩展类与对应选项数组

问题背景

现有一组基于Extension的扩展类,每个类对应专属的选项类型,需要定义一个数组类型,数组元素为「扩展类构造函数 + 对应选项」的元组,且要求TypeScript能提供精准的智能提示(如给LinkExtension的选项自动提示autoLink字段)。之前尝试的泛型方案无法实现预期的提示效果。

原始类型定义

type ExtensionOptions = { name: string }

type BoldOptions = ExtensionOptions & { boldShortcut?: string }
type ItalicOptions = ExtensionOptions & { italicShortcut?: string }
type LinkOptions = ExtensionOptions & { autoLink?: boolean }

declare class Extension {
    constructor(options: ExtensionOptions)
}

declare class BoldExtension extends Extension {
  isSelectionBold: boolean
  constructor(options: BoldOptions)
}

declare class ItalicExtension extends Extension {
  isSelectionItalic: boolean
  constructor(options: ItalicOptions)
}

declare class LinkExtension extends Extension {
  isSelectionLink: boolean
  constructor(options: LinkOptions)
}

无效的尝试方案

// 通用类型可运行但无智能提示
type Extensions = Array<[Extension, ExtensionOptions]>

// 泛型类型无法处理多类混合场景
type Extensions<T> = Array<[
  T,
  T extends new (...args: infer Options) => any
    ? Options[0]
    : never
]>

解决方案

方案1:手动定义联合元组类型

先枚举所有合法的「类+选项」组合,再将数组类型约束为该联合类型的数组:

// 定义单个扩展项的合法组合
type ExtensionEntry = 
  | [typeof BoldExtension, BoldOptions]
  | [typeof ItalicExtension, ItalicOptions]
  | [typeof LinkExtension, LinkOptions]

// 扩展数组类型
type Extensions = ExtensionEntry[]

// 使用示例(自动获得对应字段提示)
const extensions: Extensions = [
  [BoldExtension, { name: 'bold', boldShortcut: 'Ctrl+B' }],
  [ItalicExtension, { name: 'italic' }],
  [LinkExtension, { name: 'link', autoLink: true }]
]

方案2:泛型函数自动推断(更简洁)

通过辅助函数让TypeScript自动推断每个元组的类与选项的对应关系,无需手动维护联合类型:

// 辅助函数,约束数组元素的类型匹配关系
function createExtensions<T extends Array<
  [new (...args: infer Args) => Extension, Args[0]]
>>(entries: T) {
  return entries
}

// 使用示例(无需手动指定类型,自动触发智能提示)
const extensions = createExtensions([
  [BoldExtension, { name: 'bold', boldShortcut: 'Ctrl+B' }],
  [ItalicExtension, { name: 'italic', italicShortcut: 'Ctrl+I' }],
  [LinkExtension, { name: 'link', autoLink: true }]
])

无效方案的原因

你之前的Extensions<T>泛型中,T被约束为单一类型,导致数组所有元素必须是同一个T对应的元组,无法混合不同的扩展类。而上述方案通过联合类型或数组泛型约束,允许数组包含多种合法的「类+选项」组合,TypeScript会为每个元素单独做类型检查和提示。

内容的提问来源于stack exchange,提问作者U-Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 04:53:20