typescript 泛型内的 `=` 赋值操作是什么意思?

描述

举个 jQuery 声明文件 的 栗子

interface JQueryStatic {
    // ...
    <TElement extends Element = HTMLElement>(selector: JQuery.Selector, context?: Element | Document | JQuery): JQuery<TElement>;
}

如果是 <TElement extends Element>(selector: JQuery.Selector, context?: Element | Document | JQuery): JQuery<TElement> , 我理解大概是说:“可以传入一个泛型参数 TElement,且 TElement 需要满足 Element类型的约束条件”

问题

  1. <TElement extends Element = HTMLElement>, 这里的 = HTMLElement 的意义是什么 ?
  2. 这里的=赋值像是函数参数默认值,代表泛型的默认值么? 但是,由官方栗子可知,类型推论会自动确定确认 T 的类型,应该是不需要泛型的默认值的吧?

    function identity<T>(arg: T): T {
        return arg;
    }
    
    let output = identity<string>("myString");  // type of output will be 'string'
    
    // 利用了类型推论 -- 即编译器会根据传入的参数自动地帮助我们确定T的类型
    let output2 = identity("myString");  // type of output will be 'string'
阅读 8k
2 个回答

就是泛型的默认值。

阁下引用的例子里写到

编译器会根据传入的参数自动地帮助我们确定T的类型

而在JQueryStatic里,传入的参数与TElement一毛钱关系都没有,换言之,是无法自动推断的。在这种时候,就可以指定一个默认值。


题主引用的例子里写的是“传入的参数”,所以我也就沿用了这个不严谨的表达,但是看起来导致困惑了……

这里的“传入的参数”,指的是圆括号里的东西,即函数的形参。如果圆括号里面没有出现过TElement,那么就不可能根据调用时的实参去自动推断泛型。至于泛型的约束条件,可以与默认值同时出现,也可以不同时出现,两者没有必然的联系。

严格来说,“传入”这个词和“泛型参数”这个词是不能搭配的。泛型是定义时使用的,运行时会被去掉。

再补上例子吧:

function bare<TElement>(): TElement {
    return null as any as TElement;
}

const a = bare(); // typeof a === {}

function ext<TElement extends Element>(): TElement {
    return null as any as TElement;
}

const b = ext(); // typeof b === Element

function dft<TElement extends Element = HTMLElement>(): TElement {
    return null as any as TElement;
}

const c = dft(); // typeof c === HTMLElement

以上圆括号里面都没有出现过TElement

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题